Initial commit: breakpilot-core - Shared Infrastructure

Docker Compose with 24+ services:
- PostgreSQL (PostGIS), Valkey, MinIO, Qdrant
- Vault (PKI/TLS), Nginx (Reverse Proxy)
- Backend Core API, Consent Service, Billing Service
- RAG Service, Embedding Service
- Gitea, Woodpecker CI/CD
- Night Scheduler, Health Aggregator
- Jitsi (Web/XMPP/JVB/Jicofo), Mailpit

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Boenisch
2026-02-11 23:47:13 +01:00
commit ad111d5e69
244 changed files with 84288 additions and 0 deletions

171
bpmn-processes/README.md Normal file
View File

@@ -0,0 +1,171 @@
# BreakPilot BPMN Prozesse
Dieses Verzeichnis enthaelt die BPMN 2.0 Prozessdefinitionen fuer BreakPilot.
## Prozess-Uebersicht
| Datei | Prozess | Beschreibung | Status |
|-------|---------|--------------|--------|
| `classroom-lesson.bpmn` | Unterrichtsstunde | Phasenbasierte Unterrichtssteuerung | Entwurf |
| `consent-document.bpmn` | Consent-Dokument | DSB-Approval, Publishing, Monitoring | Entwurf |
| `klausur-korrektur.bpmn` | Klausurkorrektur | OCR, AI-Grading, Export | Entwurf |
| `dsr-request.bpmn` | DSR/GDPR | Betroffenenanfragen (Art. 15-20) | Entwurf |
## Verwendung
### Im BPMN Editor laden
1. Navigiere zu http://localhost:3000/admin/workflow oder http://localhost:8000/app (Workflow)
2. Klicke "Oeffnen" und waehle eine .bpmn Datei
3. Bearbeite den Prozess im Editor
4. Speichere und deploye zu Camunda
### In Camunda deployen
```bash
# Camunda starten (falls noch nicht aktiv)
docker compose --profile bpmn up -d camunda
# Prozess deployen via API
curl -X POST http://localhost:8000/api/bpmn/deployment/create \
-F "deployment-name=breakpilot-processes" \
-F "data=@classroom-lesson.bpmn"
```
### Prozess starten
```bash
# Unterrichtsstunde starten
curl -X POST http://localhost:8000/api/bpmn/process-definition/ClassroomLessonProcess/start \
-H "Content-Type: application/json" \
-d '{
"variables": {
"teacherId": {"value": "teacher-123"},
"classId": {"value": "class-7a"},
"subject": {"value": "Mathematik"}
}
}'
```
## Prozess-Details
### 1. Classroom Lesson (classroom-lesson.bpmn)
**Phasen:**
- Einstieg (Motivation, Problemstellung)
- Erarbeitung I (Einzelarbeit, Partnerarbeit, Gruppenarbeit)
- Erarbeitung II (optional)
- Sicherung (Tafel, Digital, Schueler-Praesentation)
- Transfer (Anwendungsaufgaben)
- Reflexion & Abschluss (Hausaufgaben, Notizen)
**Service Tasks:**
- `contentSuggestionDelegate` - Content-Vorschlaege basierend auf Phase
- `lessonProtocolDelegate` - Automatisches Stundenprotokoll
**Timer Events:**
- Phasen-Timer mit Warnungen
---
### 2. Consent Document (consent-document.bpmn)
**Workflow:**
1. Dokument bearbeiten (Autor)
2. DSB-Pruefung (Vier-Augen-Prinzip)
3. Bei Ablehnung: Zurueck an Autor
4. Bei Genehmigung: Veroeffentlichen
5. Benutzer benachrichtigen
6. Consent sammeln mit Deadline-Timer
7. Monitoring-Subprocess fuer jaehrliche Erneuerung
8. Archivierung bei neuer Version
**Service Tasks:**
- `publishConsentDocumentDelegate`
- `notifyUsersDelegate`
- `sendConsentReminderDelegate`
- `checkConsentStatusDelegate`
- `triggerRenewalDelegate`
- `archiveDocumentDelegate`
---
### 3. Klausur Korrektur (klausur-korrektur.bpmn)
**Workflow:**
1. OCR-Verarbeitung der hochgeladenen Klausuren
2. Qualitaets-Check (Confidence >= 85%)
3. Bei schlechter Qualitaet: Manuelle Nachbearbeitung
4. Erwartungshorizont definieren
5. AI-Bewertung mit Claude
6. Lehrer-Review mit Anpassungsmoeglichkeit
7. Noten berechnen (15-Punkte-Skala)
8. Notenbuch aktualisieren
9. Export (PDF, Excel)
10. Optional: Eltern benachrichtigen
11. Archivierung
**Service Tasks:**
- `ocrProcessingDelegate`
- `ocrQualityCheckDelegate`
- `aiGradingDelegate`
- `calculateGradesDelegate`
- `updateGradebookDelegate`
- `generateExportDelegate`
- `notifyParentsDelegate`
- `archiveExamDelegate`
- `deadlineWarningDelegate`
---
### 4. DSR Request (dsr-request.bpmn)
**GDPR Artikel:**
- Art. 15: Recht auf Auskunft (Access)
- Art. 16: Recht auf Berichtigung (Rectification)
- Art. 17: Recht auf Loeschung (Deletion)
- Art. 20: Recht auf Datenuebertragbarkeit (Portability)
**Workflow:**
1. Anfrage validieren
2. Bei ungueltig: Ablehnen
3. Je nach Typ:
- Access: Daten sammeln → Anonymisieren → Review → Export
- Deletion: Identifizieren → Genehmigen → Loeschen → Verifizieren
- Portability: Sammeln → JSON formatieren
- Rectification: Pruefen → Anwenden
4. Betroffenen benachrichtigen
5. Audit Log erstellen
**30-Tage Frist:**
- Timer-Event nach 25 Tagen fuer Eskalation an DSB
**Service Tasks:**
- `validateDSRDelegate`
- `rejectDSRDelegate`
- `collectUserDataDelegate`
- `anonymizeDataDelegate`
- `prepareExportDelegate`
- `identifyUserDataDelegate`
- `executeDataDeletionDelegate`
- `verifyDeletionDelegate`
- `collectPortableDataDelegate`
- `formatPortableDataDelegate`
- `applyRectificationDelegate`
- `notifyDataSubjectDelegate`
- `createAuditLogDelegate`
- `escalateToDSBDelegate`
## Naechste Schritte
1. **Delegates implementieren**: Java/Python Service Tasks
2. **Camunda Connect**: REST-Aufrufe zu Backend-APIs
3. **User Task Forms**: Camunda Forms oder Custom UI
4. **Timer konfigurieren**: Realistische Dauern setzen
5. **Testing**: Prozesse mit Testdaten durchlaufen
## Referenzen
- [Camunda 7 Docs](https://docs.camunda.org/manual/7.21/)
- [BPMN 2.0 Spec](https://www.omg.org/spec/BPMN/2.0/)
- [bpmn-js](https://bpmn.io/toolkit/bpmn-js/)

View File

@@ -0,0 +1,181 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="Definitions_Classroom"
targetNamespace="http://breakpilot.de/bpmn/classroom">
<bpmn:process id="ClassroomLessonProcess" name="Unterrichtsstunde" isExecutable="true">
<!-- Start Event -->
<bpmn:startEvent id="start" name="Stunde beginnen">
<bpmn:outgoing>flow_to_einstieg</bpmn:outgoing>
</bpmn:startEvent>
<!-- Phase 1: Einstieg -->
<bpmn:userTask id="phase_einstieg" name="Einstiegsphase" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="duration" label="Dauer (Minuten)" type="long" defaultValue="10" />
<camunda:formField id="activity" label="Aktivitaet" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_einstieg</bpmn:incoming>
<bpmn:outgoing>flow_to_erarbeitung1</bpmn:outgoing>
</bpmn:userTask>
<!-- Service Task: Content-Vorschlaege Einstieg -->
<bpmn:serviceTask id="suggest_einstieg" name="Content-Vorschlaege" camunda:delegateExpression="${contentSuggestionDelegate}">
<bpmn:incoming>flow_suggest_einstieg</bpmn:incoming>
<bpmn:outgoing>flow_from_suggest_einstieg</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Phase 2: Erarbeitung I -->
<bpmn:userTask id="phase_erarbeitung1" name="Erarbeitung I" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="duration" label="Dauer (Minuten)" type="long" defaultValue="15" />
<camunda:formField id="sozialform" label="Sozialform" type="enum">
<camunda:value id="einzelarbeit" name="Einzelarbeit" />
<camunda:value id="partnerarbeit" name="Partnerarbeit" />
<camunda:value id="gruppenarbeit" name="Gruppenarbeit" />
</camunda:formField>
<camunda:formField id="content" label="Lerneinheit" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_erarbeitung1</bpmn:incoming>
<bpmn:outgoing>flow_to_erarbeitung_gateway</bpmn:outgoing>
</bpmn:userTask>
<!-- Gateway: Weitere Erarbeitung? -->
<bpmn:exclusiveGateway id="erarbeitung_gateway" name="Weitere Erarbeitung?">
<bpmn:incoming>flow_to_erarbeitung_gateway</bpmn:incoming>
<bpmn:outgoing>flow_to_erarbeitung2</bpmn:outgoing>
<bpmn:outgoing>flow_to_sicherung</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Phase 2b: Erarbeitung II (optional) -->
<bpmn:userTask id="phase_erarbeitung2" name="Erarbeitung II" camunda:assignee="${teacherId}">
<bpmn:incoming>flow_to_erarbeitung2</bpmn:incoming>
<bpmn:outgoing>flow_from_erarbeitung2</bpmn:outgoing>
</bpmn:userTask>
<!-- Phase 3: Sicherung -->
<bpmn:userTask id="phase_sicherung" name="Sicherungsphase" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="duration" label="Dauer (Minuten)" type="long" defaultValue="10" />
<camunda:formField id="method" label="Methode" type="enum">
<camunda:value id="tafel" name="Tafelanschrieb" />
<camunda:value id="digital" name="Digitale Zusammenfassung" />
<camunda:value id="schueler" name="Schueler-Praesentation" />
</camunda:formField>
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_sicherung</bpmn:incoming>
<bpmn:incoming>flow_from_erarbeitung2</bpmn:incoming>
<bpmn:outgoing>flow_to_transfer</bpmn:outgoing>
</bpmn:userTask>
<!-- Phase 4: Transfer -->
<bpmn:userTask id="phase_transfer" name="Transferphase" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="duration" label="Dauer (Minuten)" type="long" defaultValue="8" />
<camunda:formField id="aufgabe" label="Transfer-Aufgabe" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_transfer</bpmn:incoming>
<bpmn:outgoing>flow_to_reflexion</bpmn:outgoing>
</bpmn:userTask>
<!-- Phase 5: Reflexion -->
<bpmn:userTask id="phase_reflexion" name="Reflexion &amp; Abschluss" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="duration" label="Dauer (Minuten)" type="long" defaultValue="5" />
<camunda:formField id="hausaufgabe" label="Hausaufgabe" type="string" />
<camunda:formField id="notizen" label="Stundennotizen" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_reflexion</bpmn:incoming>
<bpmn:outgoing>flow_to_protokoll</bpmn:outgoing>
</bpmn:userTask>
<!-- Service Task: Stundenprotokoll -->
<bpmn:serviceTask id="create_protokoll" name="Stundenprotokoll erstellen" camunda:delegateExpression="${lessonProtocolDelegate}">
<bpmn:incoming>flow_to_protokoll</bpmn:incoming>
<bpmn:outgoing>flow_to_end</bpmn:outgoing>
</bpmn:serviceTask>
<!-- End Event -->
<bpmn:endEvent id="end" name="Stunde beendet">
<bpmn:incoming>flow_to_end</bpmn:incoming>
</bpmn:endEvent>
<!-- Boundary Timer Events -->
<bpmn:boundaryEvent id="timer_einstieg" attachedToRef="phase_einstieg" cancelActivity="false">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>PT${einstiegDuration}M</bpmn:timeDuration>
</bpmn:timerEventDefinition>
<bpmn:outgoing>flow_timer_warning</bpmn:outgoing>
</bpmn:boundaryEvent>
<!-- Sequence Flows -->
<bpmn:sequenceFlow id="flow_to_einstieg" sourceRef="start" targetRef="phase_einstieg" />
<bpmn:sequenceFlow id="flow_to_erarbeitung1" sourceRef="phase_einstieg" targetRef="phase_erarbeitung1" />
<bpmn:sequenceFlow id="flow_to_erarbeitung_gateway" sourceRef="phase_erarbeitung1" targetRef="erarbeitung_gateway" />
<bpmn:sequenceFlow id="flow_to_erarbeitung2" sourceRef="erarbeitung_gateway" targetRef="phase_erarbeitung2">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsMoreWork == true}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_to_sicherung" sourceRef="erarbeitung_gateway" targetRef="phase_sicherung">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${needsMoreWork == false}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_from_erarbeitung2" sourceRef="phase_erarbeitung2" targetRef="phase_sicherung" />
<bpmn:sequenceFlow id="flow_to_transfer" sourceRef="phase_sicherung" targetRef="phase_transfer" />
<bpmn:sequenceFlow id="flow_to_reflexion" sourceRef="phase_transfer" targetRef="phase_reflexion" />
<bpmn:sequenceFlow id="flow_to_protokoll" sourceRef="phase_reflexion" targetRef="create_protokoll" />
<bpmn:sequenceFlow id="flow_to_end" sourceRef="create_protokoll" targetRef="end" />
</bpmn:process>
<!-- BPMN Diagram -->
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="ClassroomLessonProcess">
<bpmndi:BPMNShape id="start_di" bpmnElement="start">
<dc:Bounds x="152" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_einstieg_di" bpmnElement="phase_einstieg">
<dc:Bounds x="240" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_erarbeitung1_di" bpmnElement="phase_erarbeitung1">
<dc:Bounds x="390" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="erarbeitung_gateway_di" bpmnElement="erarbeitung_gateway" isMarkerVisible="true">
<dc:Bounds x="545" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_erarbeitung2_di" bpmnElement="phase_erarbeitung2">
<dc:Bounds x="520" y="200" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_sicherung_di" bpmnElement="phase_sicherung">
<dc:Bounds x="670" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_transfer_di" bpmnElement="phase_transfer">
<dc:Bounds x="820" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="phase_reflexion_di" bpmnElement="phase_reflexion">
<dc:Bounds x="970" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="create_protokoll_di" bpmnElement="create_protokoll">
<dc:Bounds x="1120" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_di" bpmnElement="end">
<dc:Bounds x="1272" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@@ -0,0 +1,206 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="Definitions_Consent"
targetNamespace="http://breakpilot.de/bpmn/consent">
<bpmn:process id="ConsentDocumentProcess" name="Consent-Dokument Workflow" isExecutable="true">
<!-- Start Event -->
<bpmn:startEvent id="start" name="Dokument erstellt">
<bpmn:outgoing>flow_to_edit</bpmn:outgoing>
</bpmn:startEvent>
<!-- User Task: Dokument bearbeiten -->
<bpmn:userTask id="edit_document" name="Dokument bearbeiten" camunda:assignee="${authorId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="title" label="Titel" type="string" />
<camunda:formField id="type" label="Dokumenttyp" type="enum">
<camunda:value id="terms" name="AGB" />
<camunda:value id="privacy" name="Datenschutzerklaerung" />
<camunda:value id="cookies" name="Cookie-Richtlinie" />
<camunda:value id="consent_form" name="Einwilligungserklaerung" />
</camunda:formField>
<camunda:formField id="content" label="Inhalt" type="string" />
<camunda:formField id="version" label="Version" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_edit</bpmn:incoming>
<bpmn:incoming>flow_rejected_to_edit</bpmn:incoming>
<bpmn:outgoing>flow_to_review</bpmn:outgoing>
</bpmn:userTask>
<!-- User Task: DSB Review -->
<bpmn:userTask id="dsb_review" name="DSB Pruefung" camunda:candidateGroups="data_protection_officer">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="approved" label="Genehmigt" type="boolean" />
<camunda:formField id="comments" label="Kommentare" type="string" />
<camunda:formField id="legalCheck" label="Rechtliche Pruefung OK" type="boolean" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_review</bpmn:incoming>
<bpmn:outgoing>flow_to_approval_gateway</bpmn:outgoing>
</bpmn:userTask>
<!-- Gateway: Genehmigt? -->
<bpmn:exclusiveGateway id="approval_gateway" name="Genehmigt?">
<bpmn:incoming>flow_to_approval_gateway</bpmn:incoming>
<bpmn:outgoing>flow_approved</bpmn:outgoing>
<bpmn:outgoing>flow_rejected</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Service Task: Veroeffentlichen -->
<bpmn:serviceTask id="publish_document" name="Dokument veroeffentlichen" camunda:delegateExpression="${publishConsentDocumentDelegate}">
<bpmn:incoming>flow_approved</bpmn:incoming>
<bpmn:outgoing>flow_to_notify</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Benutzer benachrichtigen -->
<bpmn:serviceTask id="notify_users" name="Benutzer benachrichtigen" camunda:delegateExpression="${notifyUsersDelegate}">
<bpmn:incoming>flow_to_notify</bpmn:incoming>
<bpmn:outgoing>flow_to_collect_consent</bpmn:outgoing>
</bpmn:serviceTask>
<!-- User Task: Consent sammeln (wartet auf Benutzer-Zustimmungen) -->
<bpmn:receiveTask id="collect_consent" name="Auf Zustimmungen warten">
<bpmn:incoming>flow_to_collect_consent</bpmn:incoming>
<bpmn:outgoing>flow_to_check_deadline</bpmn:outgoing>
</bpmn:receiveTask>
<!-- Boundary Timer: Deadline -->
<bpmn:boundaryEvent id="consent_deadline" attachedToRef="collect_consent" cancelActivity="false">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>P${consentDeadlineDays}D</bpmn:timeDuration>
</bpmn:timerEventDefinition>
<bpmn:outgoing>flow_to_reminder</bpmn:outgoing>
</bpmn:boundaryEvent>
<!-- Service Task: Reminder senden -->
<bpmn:serviceTask id="send_reminder" name="Reminder senden" camunda:delegateExpression="${sendConsentReminderDelegate}">
<bpmn:incoming>flow_to_reminder</bpmn:incoming>
<bpmn:outgoing>flow_back_to_collect</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Consent-Status pruefen -->
<bpmn:serviceTask id="check_consent_status" name="Consent-Status pruefen" camunda:delegateExpression="${checkConsentStatusDelegate}">
<bpmn:incoming>flow_to_check_deadline</bpmn:incoming>
<bpmn:outgoing>flow_to_active</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Intermediate Event: Dokument aktiv -->
<bpmn:intermediateThrowEvent id="document_active" name="Dokument aktiv">
<bpmn:incoming>flow_to_active</bpmn:incoming>
<bpmn:outgoing>flow_to_monitor</bpmn:outgoing>
</bpmn:intermediateThrowEvent>
<!-- Sub-Process: Monitoring -->
<bpmn:subProcess id="monitoring_subprocess" name="Consent Monitoring">
<bpmn:incoming>flow_to_monitor</bpmn:incoming>
<bpmn:outgoing>flow_to_archive</bpmn:outgoing>
<bpmn:startEvent id="monitoring_start" />
<!-- Event-based Gateway: Warte auf Events -->
<bpmn:eventBasedGateway id="event_gateway">
<bpmn:incoming>flow_from_monitoring_start</bpmn:incoming>
<bpmn:outgoing>flow_to_renewal_timer</bpmn:outgoing>
<bpmn:outgoing>flow_to_supersede_event</bpmn:outgoing>
</bpmn:eventBasedGateway>
<!-- Timer: Jaehrliche Erneuerung -->
<bpmn:intermediateCatchEvent id="renewal_timer" name="Erneuerungsdatum">
<bpmn:incoming>flow_to_renewal_timer</bpmn:incoming>
<bpmn:outgoing>flow_to_renewal_task</bpmn:outgoing>
<bpmn:timerEventDefinition>
<bpmn:timeDuration>P1Y</bpmn:timeDuration>
</bpmn:timerEventDefinition>
</bpmn:intermediateCatchEvent>
<!-- Message: Dokument ersetzt -->
<bpmn:intermediateCatchEvent id="supersede_event" name="Neue Version">
<bpmn:incoming>flow_to_supersede_event</bpmn:incoming>
<bpmn:outgoing>flow_to_monitoring_end</bpmn:outgoing>
<bpmn:messageEventDefinition messageRef="Message_Supersede" />
</bpmn:intermediateCatchEvent>
<bpmn:serviceTask id="trigger_renewal" name="Erneuerung anfordern" camunda:delegateExpression="${triggerRenewalDelegate}">
<bpmn:incoming>flow_to_renewal_task</bpmn:incoming>
<bpmn:outgoing>flow_back_to_gateway</bpmn:outgoing>
</bpmn:serviceTask>
<bpmn:endEvent id="monitoring_end" />
</bpmn:subProcess>
<!-- Service Task: Archivieren -->
<bpmn:serviceTask id="archive_document" name="Dokument archivieren" camunda:delegateExpression="${archiveDocumentDelegate}">
<bpmn:incoming>flow_to_archive</bpmn:incoming>
<bpmn:outgoing>flow_to_end</bpmn:outgoing>
</bpmn:serviceTask>
<!-- End Event -->
<bpmn:endEvent id="end" name="Workflow beendet">
<bpmn:incoming>flow_to_end</bpmn:incoming>
</bpmn:endEvent>
<!-- Sequence Flows -->
<bpmn:sequenceFlow id="flow_to_edit" sourceRef="start" targetRef="edit_document" />
<bpmn:sequenceFlow id="flow_to_review" sourceRef="edit_document" targetRef="dsb_review" />
<bpmn:sequenceFlow id="flow_to_approval_gateway" sourceRef="dsb_review" targetRef="approval_gateway" />
<bpmn:sequenceFlow id="flow_approved" sourceRef="approval_gateway" targetRef="publish_document">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved == true}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_rejected" sourceRef="approval_gateway" targetRef="edit_document">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved == false}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_rejected_to_edit" sourceRef="approval_gateway" targetRef="edit_document" />
<bpmn:sequenceFlow id="flow_to_notify" sourceRef="publish_document" targetRef="notify_users" />
<bpmn:sequenceFlow id="flow_to_collect_consent" sourceRef="notify_users" targetRef="collect_consent" />
<bpmn:sequenceFlow id="flow_to_reminder" sourceRef="consent_deadline" targetRef="send_reminder" />
<bpmn:sequenceFlow id="flow_to_check_deadline" sourceRef="collect_consent" targetRef="check_consent_status" />
<bpmn:sequenceFlow id="flow_to_active" sourceRef="check_consent_status" targetRef="document_active" />
<bpmn:sequenceFlow id="flow_to_monitor" sourceRef="document_active" targetRef="monitoring_subprocess" />
<bpmn:sequenceFlow id="flow_to_archive" sourceRef="monitoring_subprocess" targetRef="archive_document" />
<bpmn:sequenceFlow id="flow_to_end" sourceRef="archive_document" targetRef="end" />
</bpmn:process>
<!-- Messages -->
<bpmn:message id="Message_Supersede" name="DocumentSuperseded" />
<!-- BPMN Diagram -->
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="ConsentDocumentProcess">
<bpmndi:BPMNShape id="start_di" bpmnElement="start">
<dc:Bounds x="152" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="edit_document_di" bpmnElement="edit_document">
<dc:Bounds x="240" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="dsb_review_di" bpmnElement="dsb_review">
<dc:Bounds x="390" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="approval_gateway_di" bpmnElement="approval_gateway" isMarkerVisible="true">
<dc:Bounds x="545" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="publish_document_di" bpmnElement="publish_document">
<dc:Bounds x="650" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="notify_users_di" bpmnElement="notify_users">
<dc:Bounds x="800" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="collect_consent_di" bpmnElement="collect_consent">
<dc:Bounds x="950" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_di" bpmnElement="end">
<dc:Bounds x="1502" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@@ -0,0 +1,222 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="Definitions_DSR"
targetNamespace="http://breakpilot.de/bpmn/dsr">
<bpmn:process id="DSRRequestProcess" name="Data Subject Request (GDPR)" isExecutable="true">
<!-- Start Event -->
<bpmn:startEvent id="start" name="DSR eingereicht">
<bpmn:outgoing>flow_to_validate</bpmn:outgoing>
</bpmn:startEvent>
<!-- Service Task: Anfrage validieren -->
<bpmn:serviceTask id="validate_request" name="Anfrage validieren" camunda:delegateExpression="${validateDSRDelegate}">
<bpmn:incoming>flow_to_validate</bpmn:incoming>
<bpmn:outgoing>flow_to_validation_gateway</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Gateway: Anfrage gueltig? -->
<bpmn:exclusiveGateway id="validation_gateway" name="Anfrage gueltig?">
<bpmn:incoming>flow_to_validation_gateway</bpmn:incoming>
<bpmn:outgoing>flow_valid</bpmn:outgoing>
<bpmn:outgoing>flow_invalid</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Service Task: Anfrage ablehnen -->
<bpmn:serviceTask id="reject_request" name="Anfrage ablehnen" camunda:delegateExpression="${rejectDSRDelegate}">
<bpmn:incoming>flow_invalid</bpmn:incoming>
<bpmn:outgoing>flow_to_reject_end</bpmn:outgoing>
</bpmn:serviceTask>
<!-- End Event: Abgelehnt -->
<bpmn:endEvent id="end_rejected" name="DSR abgelehnt">
<bpmn:incoming>flow_to_reject_end</bpmn:incoming>
</bpmn:endEvent>
<!-- Gateway: Request-Typ -->
<bpmn:exclusiveGateway id="type_gateway" name="Request-Typ?">
<bpmn:incoming>flow_valid</bpmn:incoming>
<bpmn:outgoing>flow_access</bpmn:outgoing>
<bpmn:outgoing>flow_deletion</bpmn:outgoing>
<bpmn:outgoing>flow_portability</bpmn:outgoing>
<bpmn:outgoing>flow_rectification</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Sub-Process: Daten-Zugang (Art. 15) -->
<bpmn:subProcess id="access_subprocess" name="Daten-Zugang (Art. 15)">
<bpmn:incoming>flow_access</bpmn:incoming>
<bpmn:outgoing>flow_access_done</bpmn:outgoing>
<bpmn:startEvent id="access_start" />
<bpmn:serviceTask id="collect_data" name="Daten sammeln" camunda:delegateExpression="${collectUserDataDelegate}" />
<bpmn:serviceTask id="anonymize_data" name="Daten anonymisieren" camunda:delegateExpression="${anonymizeDataDelegate}" />
<bpmn:userTask id="review_data" name="Daten pruefen" camunda:candidateGroups="data_protection_officer">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="dataComplete" label="Daten vollstaendig" type="boolean" />
<camunda:formField id="sensitivePII" label="Sensible PII entfernt" type="boolean" />
</camunda:formData>
</bpmn:extensionElements>
</bpmn:userTask>
<bpmn:serviceTask id="prepare_export" name="Export vorbereiten" camunda:delegateExpression="${prepareExportDelegate}" />
<bpmn:endEvent id="access_end" />
</bpmn:subProcess>
<!-- Sub-Process: Daten-Loeschung (Art. 17) -->
<bpmn:subProcess id="deletion_subprocess" name="Daten-Loeschung (Art. 17)">
<bpmn:incoming>flow_deletion</bpmn:incoming>
<bpmn:outgoing>flow_deletion_done</bpmn:outgoing>
<bpmn:startEvent id="deletion_start" />
<bpmn:serviceTask id="identify_data" name="Daten identifizieren" camunda:delegateExpression="${identifyUserDataDelegate}" />
<bpmn:userTask id="approve_deletion" name="Loeschung genehmigen" camunda:candidateGroups="data_protection_officer">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="legalRetention" label="Aufbewahrungspflicht?" type="boolean" />
<camunda:formField id="deletionApproved" label="Loeschung genehmigt" type="boolean" />
</camunda:formData>
</bpmn:extensionElements>
</bpmn:userTask>
<bpmn:serviceTask id="execute_deletion" name="Daten loeschen" camunda:delegateExpression="${executeDataDeletionDelegate}" />
<bpmn:serviceTask id="verify_deletion" name="Loeschung verifizieren" camunda:delegateExpression="${verifyDeletionDelegate}" />
<bpmn:endEvent id="deletion_end" />
</bpmn:subProcess>
<!-- Sub-Process: Daten-Portabilitaet (Art. 20) -->
<bpmn:subProcess id="portability_subprocess" name="Daten-Portabilitaet (Art. 20)">
<bpmn:incoming>flow_portability</bpmn:incoming>
<bpmn:outgoing>flow_portability_done</bpmn:outgoing>
<bpmn:startEvent id="portability_start" />
<bpmn:serviceTask id="collect_portable_data" name="Portable Daten sammeln" camunda:delegateExpression="${collectPortableDataDelegate}" />
<bpmn:serviceTask id="format_data" name="Daten formatieren (JSON)" camunda:delegateExpression="${formatPortableDataDelegate}" />
<bpmn:endEvent id="portability_end" />
</bpmn:subProcess>
<!-- Sub-Process: Berichtigung (Art. 16) -->
<bpmn:subProcess id="rectification_subprocess" name="Berichtigung (Art. 16)">
<bpmn:incoming>flow_rectification</bpmn:incoming>
<bpmn:outgoing>flow_rectification_done</bpmn:outgoing>
<bpmn:startEvent id="rectification_start" />
<bpmn:userTask id="review_rectification" name="Berichtigung pruefen" camunda:candidateGroups="data_protection_officer" />
<bpmn:serviceTask id="apply_rectification" name="Daten berichtigen" camunda:delegateExpression="${applyRectificationDelegate}" />
<bpmn:endEvent id="rectification_end" />
</bpmn:subProcess>
<!-- Gateway: Zusammenfuehrung -->
<bpmn:exclusiveGateway id="merge_gateway">
<bpmn:incoming>flow_access_done</bpmn:incoming>
<bpmn:incoming>flow_deletion_done</bpmn:incoming>
<bpmn:incoming>flow_portability_done</bpmn:incoming>
<bpmn:incoming>flow_rectification_done</bpmn:incoming>
<bpmn:outgoing>flow_to_notify</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Service Task: Betroffenen benachrichtigen -->
<bpmn:serviceTask id="notify_subject" name="Betroffenen benachrichtigen" camunda:delegateExpression="${notifyDataSubjectDelegate}">
<bpmn:incoming>flow_to_notify</bpmn:incoming>
<bpmn:outgoing>flow_to_audit</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Audit Log -->
<bpmn:serviceTask id="create_audit" name="Audit Log erstellen" camunda:delegateExpression="${createAuditLogDelegate}">
<bpmn:incoming>flow_to_audit</bpmn:incoming>
<bpmn:outgoing>flow_to_end</bpmn:outgoing>
</bpmn:serviceTask>
<!-- End Event -->
<bpmn:endEvent id="end" name="DSR abgeschlossen">
<bpmn:incoming>flow_to_end</bpmn:incoming>
</bpmn:endEvent>
<!-- Boundary Timer: 30-Tage GDPR Frist -->
<bpmn:boundaryEvent id="gdpr_deadline" attachedToRef="access_subprocess" cancelActivity="false">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>P25D</bpmn:timeDuration>
</bpmn:timerEventDefinition>
<bpmn:outgoing>flow_deadline_escalation</bpmn:outgoing>
</bpmn:boundaryEvent>
<!-- Service Task: Eskalation an DSB -->
<bpmn:serviceTask id="escalate_dsb" name="Eskalation an DSB" camunda:delegateExpression="${escalateToDSBDelegate}">
<bpmn:incoming>flow_deadline_escalation</bpmn:incoming>
</bpmn:serviceTask>
<!-- Sequence Flows -->
<bpmn:sequenceFlow id="flow_to_validate" sourceRef="start" targetRef="validate_request" />
<bpmn:sequenceFlow id="flow_to_validation_gateway" sourceRef="validate_request" targetRef="validation_gateway" />
<bpmn:sequenceFlow id="flow_valid" sourceRef="validation_gateway" targetRef="type_gateway">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${valid == true}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_invalid" sourceRef="validation_gateway" targetRef="reject_request">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${valid == false}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_to_reject_end" sourceRef="reject_request" targetRef="end_rejected" />
<bpmn:sequenceFlow id="flow_access" sourceRef="type_gateway" targetRef="access_subprocess">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${requestType == 'access'}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_deletion" sourceRef="type_gateway" targetRef="deletion_subprocess">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${requestType == 'deletion'}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_portability" sourceRef="type_gateway" targetRef="portability_subprocess">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${requestType == 'portability'}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_rectification" sourceRef="type_gateway" targetRef="rectification_subprocess">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${requestType == 'rectification'}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_access_done" sourceRef="access_subprocess" targetRef="merge_gateway" />
<bpmn:sequenceFlow id="flow_deletion_done" sourceRef="deletion_subprocess" targetRef="merge_gateway" />
<bpmn:sequenceFlow id="flow_portability_done" sourceRef="portability_subprocess" targetRef="merge_gateway" />
<bpmn:sequenceFlow id="flow_rectification_done" sourceRef="rectification_subprocess" targetRef="merge_gateway" />
<bpmn:sequenceFlow id="flow_to_notify" sourceRef="merge_gateway" targetRef="notify_subject" />
<bpmn:sequenceFlow id="flow_to_audit" sourceRef="notify_subject" targetRef="create_audit" />
<bpmn:sequenceFlow id="flow_to_end" sourceRef="create_audit" targetRef="end" />
<bpmn:sequenceFlow id="flow_deadline_escalation" sourceRef="gdpr_deadline" targetRef="escalate_dsb" />
</bpmn:process>
<!-- BPMN Diagram -->
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="DSRRequestProcess">
<bpmndi:BPMNShape id="start_di" bpmnElement="start">
<dc:Bounds x="152" y="252" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="validate_request_di" bpmnElement="validate_request">
<dc:Bounds x="240" y="230" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="validation_gateway_di" bpmnElement="validation_gateway" isMarkerVisible="true">
<dc:Bounds x="395" y="245" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="type_gateway_di" bpmnElement="type_gateway" isMarkerVisible="true">
<dc:Bounds x="545" y="245" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_di" bpmnElement="end">
<dc:Bounds x="1502" y="252" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>

View File

@@ -0,0 +1,215 @@
<?xml version="1.0" encoding="UTF-8"?>
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
xmlns:camunda="http://camunda.org/schema/1.0/bpmn"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="Definitions_Klausur"
targetNamespace="http://breakpilot.de/bpmn/klausur">
<bpmn:process id="KlausurKorrekturProcess" name="Klausurkorrektur Workflow" isExecutable="true">
<!-- Start Event -->
<bpmn:startEvent id="start" name="Klausuren hochgeladen">
<bpmn:outgoing>flow_to_ocr</bpmn:outgoing>
</bpmn:startEvent>
<!-- Service Task: OCR Verarbeitung -->
<bpmn:serviceTask id="ocr_processing" name="OCR Verarbeitung" camunda:delegateExpression="${ocrProcessingDelegate}">
<bpmn:incoming>flow_to_ocr</bpmn:incoming>
<bpmn:outgoing>flow_to_quality_check</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Qualitaets-Check -->
<bpmn:serviceTask id="quality_check" name="OCR Qualitaets-Check" camunda:delegateExpression="${ocrQualityCheckDelegate}">
<bpmn:incoming>flow_to_quality_check</bpmn:incoming>
<bpmn:outgoing>flow_to_quality_gateway</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Gateway: OCR Qualitaet ausreichend? -->
<bpmn:exclusiveGateway id="quality_gateway" name="OCR Qualitaet OK?">
<bpmn:incoming>flow_to_quality_gateway</bpmn:incoming>
<bpmn:outgoing>flow_quality_ok</bpmn:outgoing>
<bpmn:outgoing>flow_quality_bad</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- User Task: Manuelle Nachbearbeitung -->
<bpmn:userTask id="manual_ocr_fix" name="Manuelle OCR-Korrektur" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="correctedText" label="Korrigierter Text" type="string" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_quality_bad</bpmn:incoming>
<bpmn:outgoing>flow_from_manual_fix</bpmn:outgoing>
</bpmn:userTask>
<!-- User Task: Erwartungshorizont definieren -->
<bpmn:userTask id="define_expectations" name="Erwartungshorizont" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="criteria" label="Bewertungskriterien" type="string" />
<camunda:formField id="maxPoints" label="Maximale Punktzahl" type="long" />
<camunda:formField id="useTemplate" label="Template verwenden" type="boolean" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_quality_ok</bpmn:incoming>
<bpmn:incoming>flow_from_manual_fix</bpmn:incoming>
<bpmn:outgoing>flow_to_ai_grading</bpmn:outgoing>
</bpmn:userTask>
<!-- Service Task: AI Bewertung -->
<bpmn:serviceTask id="ai_grading" name="AI-Bewertung (Claude)" camunda:delegateExpression="${aiGradingDelegate}">
<bpmn:incoming>flow_to_ai_grading</bpmn:incoming>
<bpmn:outgoing>flow_to_teacher_review</bpmn:outgoing>
</bpmn:serviceTask>
<!-- User Task: Lehrer-Review -->
<bpmn:userTask id="teacher_review" name="Lehrer-Review" camunda:assignee="${teacherId}">
<bpmn:extensionElements>
<camunda:formData>
<camunda:formField id="adjustedGrade" label="Angepasste Bewertung" type="long" />
<camunda:formField id="comments" label="Kommentare" type="string" />
<camunda:formField id="approved" label="Bewertung final" type="boolean" />
</camunda:formData>
</bpmn:extensionElements>
<bpmn:incoming>flow_to_teacher_review</bpmn:incoming>
<bpmn:outgoing>flow_to_review_gateway</bpmn:outgoing>
</bpmn:userTask>
<!-- Gateway: Review abgeschlossen? -->
<bpmn:exclusiveGateway id="review_gateway" name="Review OK?">
<bpmn:incoming>flow_to_review_gateway</bpmn:incoming>
<bpmn:outgoing>flow_review_ok</bpmn:outgoing>
<bpmn:outgoing>flow_review_adjust</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Service Task: Noten berechnen -->
<bpmn:serviceTask id="calculate_grades" name="Noten berechnen" camunda:delegateExpression="${calculateGradesDelegate}">
<bpmn:incoming>flow_review_ok</bpmn:incoming>
<bpmn:outgoing>flow_to_gradebook</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: In Notenbuch uebertragen -->
<bpmn:serviceTask id="update_gradebook" name="Notenbuch aktualisieren" camunda:delegateExpression="${updateGradebookDelegate}">
<bpmn:incoming>flow_to_gradebook</bpmn:incoming>
<bpmn:outgoing>flow_to_export</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Export generieren -->
<bpmn:serviceTask id="generate_export" name="Export generieren" camunda:delegateExpression="${generateExportDelegate}">
<bpmn:incoming>flow_to_export</bpmn:incoming>
<bpmn:outgoing>flow_to_notify_gateway</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Gateway: Eltern benachrichtigen? -->
<bpmn:exclusiveGateway id="notify_gateway" name="Eltern benachrichtigen?">
<bpmn:incoming>flow_to_notify_gateway</bpmn:incoming>
<bpmn:outgoing>flow_notify_yes</bpmn:outgoing>
<bpmn:outgoing>flow_notify_no</bpmn:outgoing>
</bpmn:exclusiveGateway>
<!-- Service Task: Eltern benachrichtigen -->
<bpmn:serviceTask id="notify_parents" name="Eltern benachrichtigen" camunda:delegateExpression="${notifyParentsDelegate}">
<bpmn:incoming>flow_notify_yes</bpmn:incoming>
<bpmn:outgoing>flow_from_notify</bpmn:outgoing>
</bpmn:serviceTask>
<!-- Service Task: Archivieren -->
<bpmn:serviceTask id="archive_exam" name="Klausur archivieren" camunda:delegateExpression="${archiveExamDelegate}">
<bpmn:incoming>flow_notify_no</bpmn:incoming>
<bpmn:incoming>flow_from_notify</bpmn:incoming>
<bpmn:outgoing>flow_to_end</bpmn:outgoing>
</bpmn:serviceTask>
<!-- End Event -->
<bpmn:endEvent id="end" name="Korrektur abgeschlossen">
<bpmn:incoming>flow_to_end</bpmn:incoming>
</bpmn:endEvent>
<!-- Boundary Timer: Korrektur-Deadline -->
<bpmn:boundaryEvent id="correction_deadline" attachedToRef="teacher_review" cancelActivity="false">
<bpmn:timerEventDefinition>
<bpmn:timeDuration>P${correctionDeadlineDays}D</bpmn:timeDuration>
</bpmn:timerEventDefinition>
<bpmn:outgoing>flow_deadline_warning</bpmn:outgoing>
</bpmn:boundaryEvent>
<!-- Service Task: Deadline-Warnung -->
<bpmn:serviceTask id="deadline_warning" name="Deadline-Warnung" camunda:delegateExpression="${deadlineWarningDelegate}">
<bpmn:incoming>flow_deadline_warning</bpmn:incoming>
</bpmn:serviceTask>
<!-- Sequence Flows -->
<bpmn:sequenceFlow id="flow_to_ocr" sourceRef="start" targetRef="ocr_processing" />
<bpmn:sequenceFlow id="flow_to_quality_check" sourceRef="ocr_processing" targetRef="quality_check" />
<bpmn:sequenceFlow id="flow_to_quality_gateway" sourceRef="quality_check" targetRef="quality_gateway" />
<bpmn:sequenceFlow id="flow_quality_ok" sourceRef="quality_gateway" targetRef="define_expectations">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${ocrConfidence >= 0.85}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_quality_bad" sourceRef="quality_gateway" targetRef="manual_ocr_fix">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${ocrConfidence &lt; 0.85}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_from_manual_fix" sourceRef="manual_ocr_fix" targetRef="define_expectations" />
<bpmn:sequenceFlow id="flow_to_ai_grading" sourceRef="define_expectations" targetRef="ai_grading" />
<bpmn:sequenceFlow id="flow_to_teacher_review" sourceRef="ai_grading" targetRef="teacher_review" />
<bpmn:sequenceFlow id="flow_to_review_gateway" sourceRef="teacher_review" targetRef="review_gateway" />
<bpmn:sequenceFlow id="flow_review_ok" sourceRef="review_gateway" targetRef="calculate_grades">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved == true}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_review_adjust" sourceRef="review_gateway" targetRef="ai_grading">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${approved == false}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_to_gradebook" sourceRef="calculate_grades" targetRef="update_gradebook" />
<bpmn:sequenceFlow id="flow_to_export" sourceRef="update_gradebook" targetRef="generate_export" />
<bpmn:sequenceFlow id="flow_to_notify_gateway" sourceRef="generate_export" targetRef="notify_gateway" />
<bpmn:sequenceFlow id="flow_notify_yes" sourceRef="notify_gateway" targetRef="notify_parents">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${notifyParents == true}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_notify_no" sourceRef="notify_gateway" targetRef="archive_exam">
<bpmn:conditionExpression xsi:type="bpmn:tFormalExpression">${notifyParents == false}</bpmn:conditionExpression>
</bpmn:sequenceFlow>
<bpmn:sequenceFlow id="flow_from_notify" sourceRef="notify_parents" targetRef="archive_exam" />
<bpmn:sequenceFlow id="flow_to_end" sourceRef="archive_exam" targetRef="end" />
<bpmn:sequenceFlow id="flow_deadline_warning" sourceRef="correction_deadline" targetRef="deadline_warning" />
</bpmn:process>
<!-- BPMN Diagram -->
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="KlausurKorrekturProcess">
<bpmndi:BPMNShape id="start_di" bpmnElement="start">
<dc:Bounds x="152" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ocr_processing_di" bpmnElement="ocr_processing">
<dc:Bounds x="240" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="quality_check_di" bpmnElement="quality_check">
<dc:Bounds x="390" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="quality_gateway_di" bpmnElement="quality_gateway" isMarkerVisible="true">
<dc:Bounds x="545" y="95" width="50" height="50" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="manual_ocr_fix_di" bpmnElement="manual_ocr_fix">
<dc:Bounds x="520" y="200" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="define_expectations_di" bpmnElement="define_expectations">
<dc:Bounds x="650" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="ai_grading_di" bpmnElement="ai_grading">
<dc:Bounds x="800" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="teacher_review_di" bpmnElement="teacher_review">
<dc:Bounds x="950" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="calculate_grades_di" bpmnElement="calculate_grades">
<dc:Bounds x="1100" y="80" width="100" height="80" />
</bpmndi:BPMNShape>
<bpmndi:BPMNShape id="end_di" bpmnElement="end">
<dc:Bounds x="1702" y="102" width="36" height="36" />
</bpmndi:BPMNShape>
</bpmndi:BPMNPlane>
</bpmndi:BPMNDiagram>
</bpmn:definitions>