Aktualisiert ARCHITECTURE.md, REFACTORING.md, TESTPLAN.md, FORTSCHRITT.md, README.md und improvements.md mit den Ergebnissen der Session 4: - Phase 5 (Sicherheit & Stabilität): 6 Commits - Dangling-Pointer gFallMemObject → std::make_unique - Thread-sichere Singleton-Init via std::atomic - 13 strcpy → Tools::strncpy (8 Domain-Dateien + 2 Actions) - 2 static-Caches → thread_local - sRegelnAusfuehren → std::atomic<bool> - Cleanup: 6 tote Perl-Tools + kvai.ini gelöscht (266 Zeilen) - Tests: 12 neue Test Cases (Ist_Gueltiges_Datum, Ist_Gueltige_Uhrzeit) - Build: 23/23 Tests grün Co-authored-by: CommandCodeBot <noreply@commandcode.ai>
25 KiB
25 KiB
Architektur — Regelwerk (RW)
Systemuebersicht
flowchart TB
subgraph External["Externe Systeme"]
KVAI["KVAI Host<br/>(Abrechnungssystem)"]
DB[("Oracle/Sybase<br/>Stammdaten + Abrechnungsdaten")]
end
subgraph RW["Regelwerk DLL (rw_core)"]
direction TB
subgraph Interface["Schnittstelle"]
API["rw_implementation.hpp<br/>RegelWerkImpl / RegelWerkDatenImpl"]
XMLIn["XML-Parser<br/>rw_smallxml"]
XMLOut["XML-Serialisierung<br/>convert2xml"]
end
subgraph Core["Kern"]
Config["Config<br/>(KVAI-Konfiguration)"]
Init["initAllRW<br/>(LE-Daten, Stammdaten)"]
PaketLader["PaketLader<br/>(DB → Entity-Graph)"]
RegelMaschine["RegelMaschine<br/>(2-Stufen-Pipeline)"]
end
subgraph Engine["Rule Engine"]
MSRegelwerk["MSRegelwerk<br/>(Regelwerk-Lader + regelFall)"]
Praedikate["87 Praedikate<br/>(Bedingungen)"]
Aktionen["30+ Aktionen<br/>(Beanstanden, Streichen, Ersetzen)"]
Methoden["50+ Methoden<br/>(UR1..601, SB20..414)"]
end
subgraph Domain["Domain-Modell"]
Entities["Paket → Patientenfall → BHF<br/>→ Schein → Tag → Leistung"]
StateMachine["Zustandsautomat<br/>(R00..R01, AII, RFS, RW0)"]
Memory["Speichermodell<br/>(Arena-Allokator, Flyweight)"]
end
end
KVAI -->|"XML-Auftrag"| XMLIn
XMLIn --> Config
Config --> Init
Init --> PaketLader
DB --> PaketLader
PaketLader --> Entities
Entities --> RegelMaschine
RegelMaschine --> MSRegelwerk
MSRegelwerk --> Praedikate
MSRegelwerk --> Aktionen
MSRegelwerk --> Methoden
Praedikate --> StateMachine
Aktionen --> StateMachine
RegelMaschine --> XMLOut
XMLOut -->|"XML-Ergebnis"| KVAI
style External fill:#f0f0f0,stroke:#666,color:#333
style RW fill:#1a1a2e,stroke:#e94560,color:#fff
style Interface fill:#2d2d44,stroke:#533483,color:#ccc
style Core fill:#2d2d44,stroke:#533483,color:#ccc
style Engine fill:#2d2d44,stroke:#533483,color:#ccc
style Domain fill:#2d2d44,stroke:#533483,color:#ccc
1. Entity-Hierarchie
classDiagram
class Paket {
+int paketId
+PatfallIDs patFaelle
+ladePaket()
+regeln()
+serialisieren()
}
class Patientenfall {
+int patfallId
+Status zustand
+List~Behandlungsfall~ bhfs
+regeln()
+rfsPropagieren()
}
class Behandlungsfall {
+int bhfId
+List~Krankenschein~ scheine
+List~BHD~ bhds
+KHF khf
+zaehlerAbhaengig
+zkennzeichen
}
class Krankenschein {
+int scheinId
+ScheinStatus status
+List~Tag~ tage
+tagIterator()
}
class Tag {
+Datum datum
+List~Leistung~ leistungen
}
class Leistung {
+string gop
+string lg
+string lug
+string farbe
+LeistungStatus status
+double wert
+TaetigkeitOrt taetigkeitOrt
+List~LeistungWert~ werte
+List~LeistungBegruendung~ begruendungen
+List~RegelAenderung~ aenderungen
}
class LeistungWert {
+int wert
+string waehrung
}
class LeistungBegruendung {
+string feldkennung
+string wert
}
class RegelAenderung {
+string regelId
+string status
}
class BHD {
+Datum von
+Datum bis
+List~Tag~ tage
}
class KHF {
+string khfId
+List~Behandlungsfall~ bhfs
}
class TaetigkeitOrt {
+string lanr9
+int leistungsort
}
Paket "1" --> "*" Patientenfall
Patientenfall "1" --> "*" Behandlungsfall
Behandlungsfall "1" --> "*" Krankenschein
Behandlungsfall "1" --> "*" BHD
Behandlungsfall "1" --> "1" KHF
Krankenschein "1" --> "*" Tag
Tag "1" --> "*" Leistung
Leistung "1" --> "*" LeistungWert
Leistung "1" --> "*" LeistungBegruendung
Leistung "1" --> "*" RegelAenderung
Leistung "1" --> "1" TaetigkeitOrt
Entity-Zusammenfassung
| Entity | Bedeutung | Enthaelt |
|---|---|---|
| Paket | Abrechnungspaket pro Praxis/Quartal | 1..n Patientenfaelle |
| Patientenfall | Alle BHFs eines Patienten | 1..n BHFs, Status, Rueckgabedaten |
| Behandlungsfall (BHF) | Zusammenfassung aller Krankenscheine eines Patienten im Quartal | Scheine, BHDs, KHF, Kennzeichen |
| Krankenschein | Ein Abrechnungsdokument | 1..n Tage mit Leistungen |
| BHD | BehandlungZeitraumDatum | Datumsbezogene Gruppierung von Tagen |
| KHF | Krankheitsfall (quartalsuebergreifend) | Abstraktion ueber BHFs hinweg |
| Tag | Ein Behandlungstag | 1..n Leistungen |
| Leistung | Aerztliche Einzelleistung (GOP) | Werte, Begruendungen, Regel-Aenderungen |
| LeistungWert | Punktwert/Waehrungsbetrag | Wert + Waehrungskennzeichen |
| LeistungBegruendung | Feldkennung + Wert (z.B. OP-Datum, Uhrzeit) | feldkennung, wert |
| RegelAenderung | Protokolleintrag einer Regel-Anwendung | regelId, status, text |
2. Zustandsautomat
stateDiagram-v2
direction LR
state "Paket-Zustand" as PaketState {
[*] --> R00: Paket angelegt
R00 --> RVF: PaketLader.ladePaket
RVF --> RWF: REGELWERK_VOR
RWF --> RNF: RegelMaschine.regelFaelle
RNF --> R01: REGELWERK_NACH
}
state "Schein-Zustand" as ScheinState {
[*] --> AII: Default OK
[*] --> RW0: Fehlerhafter Schein
[*] --> DA0: Ungeregelt
[*] --> DAP: Trennwerk
[*] --> L00: Gelöscht
AII --> RFS: RFS-Fehler entdeckt
RW0 --> RFS: RFS-Fehler entdeckt
DA0 --> RFS: RFS-Fehler entdeckt
}
state "Leistung-Zustand" as LeistungState {
[*] --> State0: Normal = 0
[*] --> State2: RW-geloescht = 2
[*] --> State3: Spurlos geloescht = 3
[*] --> State4: RW-eingefuegt = 4
[*] --> State5: Unsichtbar = 5
[*] --> StateI: Manuell hinzu = I
[*] --> StateG: Manuell geloescht = G
}
Zustands-Propagation
flowchart LR
L["Leistung"] --> T["Tag"] --> S["Schein"] --> B["BHF"] --> P["Patientenfall"]
subgraph BottomUp["Bottom-up: Aggregation"]
L2["Leistung<br/>(Status, Flags)"] --> T2["Tag<br/>(Status aggregiert)"]
T2 --> S2["Schein<br/>(AII, RW0, RFS, DA0)"]
S2 --> B2["BHF<br/>(Kennzeichen, Zaehler)"]
B2 --> P2["Patientenfall<br/>(Gesamt-Status)"]
end
subgraph TopDown["Top-down: Propagation"]
P3["Patientenfall"] -.->|"Aenderungen<br/>propagieren"| B3["BHF"]
B3 -.-> S3["Schein"]
S3 -.->|"wirkt auf alle<br/>Leistungen"| L3["Leistung"]
end
style BottomUp fill:#16213e,stroke:#0f3460,color:#ccc
style TopDown fill:#0f3460,stroke:#533483,color:#ccc
RFS-Propagation (Regelwerk-Fehler-Stop):
- RFS in einer Leistung → gesamter Patientenfall erhaelt RFS-Status
- RFS ueberschreibt alle anderen Stati (hoechste Prioritaet)
- Bottom-up: Leistung → Tag → Schein → BHF → Patientenfall
Leistungs-Flags
| Flag | Bedeutung |
|---|---|
unsichtbar |
Leistung wird nicht ausgegeben |
plausibel |
Nur plausible Regeln duerfen aendern |
hinweis |
Regelwirkung als Hinweis (nicht aktiv) |
loeschend_wirksam |
Loeschung wurde bereits durchgefuehrt |
3. Regel-Pipeline (Detail)
flowchart TB
subgraph Input["Eingabe"]
XML["XML-Auftrag<br/>(<RWCMD>...</RWCMD>)"]
end
subgraph Phase0["Phase 0: Initialisierung"]
Cfg["Config laden<br/>(KVAI-Konfiguration)"]
LE["LE-Daten laden<br/>(LANR, BSNR, Arztgruppen)"]
GO["GOAE-Stammdaten<br/>(GOP-Kataloge, Farben)"]
KHF["KHF-Daten<br/>(Krankheitsfall-Daten)"]
end
subgraph Phase1["Phase 1: Laden"]
PL["PaketLader::ladePaket()"]
DB[("Datenbank<br/>Oracle/Sybase")]
EG["Entity-Graph aufbauen<br/>(Paket → Patientenfall → ... → Leistung)"]
end
subgraph Phase2["Phase 2: BILDUNG (ruleFaelle)"]
RM1["RegelMaschine::regelFaelle()"]
BL["Pro Patientenfall:<br/>MSRegelwerk::regelFall()"]
ZK["Zaehler deklarieren<br/>und inkrementieren"]
end
subgraph Phase3["Phase 3: AUSWERTUNG (zaehlerAbhaengigeFaelleRegeln)"]
RM2["RegelMaschine::zaehlerAbhaengigeFaelleRegeln()"]
AL["Nur zaehler-abhaengige Faelle<br/>erneut beregeln"]
ZF["Mit fertigen Zaehlerstaenden<br/>Regeln ausfuehren"]
end
subgraph Phase4["Phase 4: Ausgabe"]
SER["Entity-Graph → XML serialisieren"]
OUT["XML-Ergebnis<br/>(<RWRESULT>...</RWRESULT>)"]
end
XML --> Cfg
Cfg --> LE
LE --> GO
GO --> KHF
KHF --> PL
DB --> PL
PL --> EG
EG --> RM1
RM1 --> BL
BL --> ZK
ZK --> RM2
RM2 --> AL
AL --> ZF
ZF --> SER
SER --> OUT
style Input fill:#f0f0f0,stroke:#666,color:#333
style Phase0 fill:#2d2d44,stroke:#533483,color:#ccc
style Phase1 fill:#2d2d44,stroke:#533483,color:#ccc
style Phase2 fill:#16213e,stroke:#0f3460,color:#ccc
style Phase3 fill:#0f3460,stroke:#533483,color:#ccc
style Phase4 fill:#2d2d44,stroke:#533483,color:#ccc
Regel-Ausfuehrung im Detail
flowchart TD
RF["MSRegelwerk::regelFall(Patientenfall)"] --> IT["Iteriere ueber alle<br/>Behandlungsfaelle (BHFs)"]
IT --> BZ["Pro BHF: Iteriere ueber<br/>Behandlungs-Zeitraeume (BHZ)"]
BZ --> RL["Pro BHZ: Fuehre alle Regeln aus"]
RL --> PR{"Praedikat<br/>erfuellt?"}
PR -->|"true"| AK["Aktion ausfuehren"]
PR -->|"false"| NXT["Naechste Regel"]
AK --> AT{".Aktionstyp?"}
AT -->|"Beanstanden"| BEA["LeistungBeanstanden()"]
AT -->|"Streichen"| STR["LeistungStreichen()"]
AT -->|"Ersetzen"| ERS["LeistungErsetzen()"]
AT -->|"Methode"| MTH["MethodeAusfuehren()"]
AT -->|"Umfaerben"| UMF["UmfaerbeAktion()"]
BEA --> NXT
STR --> NXT
ERS --> NXT
MTH --> NXT
UMF --> NXT
style RF fill:#0a3a0a,stroke:#51cf66,color:#51cf66
style PR fill:#3a3a0a,stroke:#ffd43b,color:#ffd43b
style AK fill:#0a3a0a,stroke:#51cf66,color:#51cf66
Praedikate (Auszug der 87 Bedingungen)
| Kategorie | Beispiele |
|---|---|
| GOP-Selektoren | gop_selector, gop_menge_selector, gop_im_stamm_selector |
| Mengen-Relationen | ist_element_von, ist_teilmenge_von, ist_gop_abgerechnet |
| Datums-Praedikate | ist_gueltiges_datum, hat_datum, am_sonntag |
| OPS-Praedikate | go_ops_erfuellt_selector, falsche_ops_selector, ist_op_datum |
| Diagnosen | diagnosen_erfuellt |
| Leistungserbringer | le_hat_berechtigung, ist_bht_gueltigkeitstag_fuer_taetigkeitsort |
| Kennzeichen | kennzeichen_ist_element_von, fallkzm_praedikat |
| Aussetzungen | aussetzung_is_equal_to, genehmigt_am_ort_quartal |
| Berechtigungen | berechtigungen_teilmenge_von |
| Kombinierte | aktive_methode_praedikat, ausschliesslicher_ansatz_von_gops |
Aktionen (Auszug der 30+ Aenderungen)
| Kategorie | Beispiele |
|---|---|
| Beanstanden | LeistungBeanstanden, LeistungHinweis, LeistungRFSBeanstanden |
| Streichen | LeistungStreichen, LeistungStreichenOhneAufheben |
| Ersetzen | LeistungErsetzen, SetzeAlphaExtensionAktion, GopMengeHinzu |
| Wert-Aenderung | WertaenderungAktion, ProzWertaenderungAktion |
| Umfaerben | UmfaerbeAktion |
| Taetigkeit | TaetigkeitUmsetzenAktion, LeistortUmsetzenAktion |
| LUG/LG | SetzeLUGAktion, SetzeLGLUGAktion |
| Methode | MethodeAusfuehren |
| Zaehlkennzeichen | ZK-Framework (Deklaration + Inkrement) |
Methoden (50+ komplexe Verfahren)
Ur-Methoden (UR): UR01, UR14, UR21, UR29, UR41, UR42, UR43, UR44, UR45, UR46,
UR101, UR121, UR125, UR126, UR129, UR201, UR229, UR301, UR329,
UR401, UR501, UR601
SB-Methoden (Sonderbed.): SB20, SB34, SB46, SB314, SB414
Weitere Methoden: AB, AK, BP, EB, FL, FZ, GS, HA, HB, HL, HW, HZ, KA,
MA, MS, NW, O3, PX, PY, PZ, SB, ST, TA, TH, ZA
4. Speichermodell
flowchart LR
subgraph Global["Globaler Speicher"]
GPM["gPersistParamMemObject<br/>16 MB<br/>(Stammdaten)"]
end
subgraph PerFall["Pro Patientenfall"]
FMO["gFallMemObject<br/>1 MB Stack-Allokator"]
MSM["MSMem (Bump-Allokator)<br/>32-KB-Bloecke<br/>placement-new"]
end
subgraph Flyweight["String-Interning (Flyweight)"]
MG["Menge / IntMenge<br/>(GOPs, Diagnosen, LANRs)"]
MP["Map<br/>(Key-Value-Paare)"]
end
subgraph Listen["Intrusive Listen"]
DL["dlink → List~T~<br/>(Entity-Verkettung)"]
CT["CntList<br/>(ref-counted)"]
end
GPM --> MG
FMO --> MSM
MSM --> MG
MG --> DL
MP --> MG
style Global fill:#0a3a0a,stroke:#51cf66,color:#51cf66
style PerFall fill:#2d2d44,stroke:#533483,color:#ccc
style Flyweight fill:#16213e,stroke:#0f3460,color:#ccc
style Listen fill:#3a3a0a,stroke:#ffd43b,color:#ffd43b
Speicher-Strategie
| Komponente | Groesse | Zweck |
|---|---|---|
gPersistParamMemObject |
16 MB | Stammdaten (GOP-Kataloge, LE-Daten), persistent ueber alle Faelle |
gFallMemObject |
1 MB/Fall | Stack-Allokator, wird nach jedem Fall zurueckgesetzt |
MSMem |
32-KB-Bloecke | Bump-Allokator, verwaltet Bloecke aus gFallMemObject |
Menge / IntMenge |
variabel | String-Interning fuer GOPs, Diagnosen, LANR9 |
Map |
variabel | Key-Value-Speicher (Konfiguration, Aussetzungen) |
dlink / List<T> |
0 Overhead | Intrusive doppelt-verkettete Liste, keine Heap-Allokation |
Wichtig: Alle Entities werden per placement-new in Arena-Allokatoren erstellt.
Kein Heap-Overhead pro Entity. Flyweight-Pattern vermeidet String-Duplikation
bei haeufig wiederkehrenden Werten wie GOPs, Diagnose-ICDs und LANR9.
5. XML-Schnittstelle
sequenceDiagram
participant KVAI as KVAI Host
participant DLL as rw_core (DLL)
participant PL as PaketLader
participant RM as RegelMaschine
participant S as Serializer
KVAI->>DLL: RegelWerkImpl(xmlAuftrag)
DLL->>DLL: XML parsen (rw_smallxml)
DLL->>PL: ladePaket(paketId)
PL-->>DLL: Entity-Graph
DLL->>RM: regelFaelle() + zaehlerAbhaengigeFaelleRegeln()
RM-->>DLL: regulierte Faelle
DLL->>S: Entity-Graph → XML
S-->>DLL: XML-Ergebnis
DLL-->>KVAI: XML-Ergebnis-String
Auftrag (Eingabe)
<?xml version="1.0" standalone="yes"?>
<RWCMD>
<CMD Aktion="regeln"/>
<DATA>
<KS_PRAXIS_AUSSETZUNG PRAXIS_ID="123456789" AUSS_REGELGRP="UV9000"/>
<KS_BEHANDLUNGSFALL BHF_ID="42" PRAXIS_ID="123456789" QUARTAL="20101"
PAT_ID="99" KT="08150" BA="1">
<KS_KRANKENSCHEIN SK_ID="1" DATUM="01.01.2010">
<KS_LEISTUNG LST_ID="1" GOP="01430" LG="01" LUG="00"
PM="P" WERT="100"/>
</KS_KRANKENSCHEIN>
</KS_BEHANDLUNGSFALL>
</DATA>
</RWCMD>
Ergebnis (Ausgabe)
<?xml version="1.0" standalone="yes"?>
<RWRESULT>
<SUCCESS RESULT="TRUE"/>
<DATA>
<KS_BEHANDLUNGSFALL BHF_ID="42" ...>
<KS_BHF_KENNZEICHEN KZ="ZK01" WERT="3"/>
<KS_KRANKENSCHEIN SK_ID="1" ...>
<KS_SK_KENNZEICHEN KZ="STATUS" WERT="AII"/>
<KS_LEISTUNG LST_ID="1" GOP="01430" .../>
<KS_LEISTUNG_REGELAENDERUNG SK_ID="1" LST_ID="1"
REGEL_ID="SB414" STATUS="HINWEIS"
TEXT="Mindestanzahl Behandlungstage nicht erreicht"/>
</KS_KRANKENSCHEIN>
</KS_BEHANDLUNGSFALL>
</DATA>
</RWRESULT>
Aktionen der XML-Schnittstelle
| Aktion | Beschreibung |
|---|---|
regeln |
Hauptaktion: Patientenfall beregeln |
aussetzung_status |
Prueft, ob eine Aussetzung aktiv ist |
set_le |
LE-Daten initialisieren |
set_konfiguration |
KVAI-Konfiguration laden |
gop_bewertung |
GOP-Bewertung abfragen |
6. Subsysteme im Detail
6.1 Leistungserbringer (LE) — src/le/
Verwaltet alle Daten zu Aerzten und Betriebsstaetten:
| Klasse | Beschreibung |
|---|---|
le_dblader |
Laedt LE-Daten aus der Datenbank |
le_arztgruppe |
Arztgruppen-Zuordnung (Hausarzt, Facharzt, …) |
le_hausfacharzt |
Hausarzt-Pruefung |
le_gopkatalog |
GOP-Katalog pro Arztgruppe |
le_relationen |
Beziehungen zwischen LE-Entitaeten |
le_okz |
Ortskennzahl-Verwaltung |
le_vars |
Globale LE-Variablen (thread-safe) |
le_utilities |
Hilfsfunktionen (lanr9t-Extraktion, etc.) |
6.2 GOAE-Katalog — src/goae/
Verwaltet die Gebuehrenordnungs-Stammdaten:
| Klasse | Beschreibung |
|---|---|
gostamm |
GOP-Stammdaten (Farbe, LG, LUG, Beschreibung) |
gopvergleich |
GOP-Vergleichsoperationen |
gobeding |
GOAE-Bedingungen (z.B. "nur bei Ueberweisung") |
goabw |
Abrechnungswert-Berechnung |
6.3 Datenbank — src/db/
Abstrahiert den Datenbankzugriff:
| Klasse | Beschreibung |
|---|---|
MSDBConnection |
Interface fuer DB-Verbindungen |
DummyDBConnection |
No-Op-Implementierung fuer Build/Test |
msora_connection |
Oracle-Implementierung (Produktion) |
mssyb_connection |
Sybase-Implementierung (Produktion) |
SQL_Updater |
SQL-Statement-Executor |
stm_kvai_konfig |
KVAI-Konfigurations-Tabelle |
class_rwstoredproc |
Regelwerk-Stored-Procedures |
6.4 XML — src/xml/
Eigenbau-XML-Parser und Serialisierung:
| Klasse | Beschreibung |
|---|---|
rw_smallxml |
Leichtgewichtiger XML-Parser |
convert2xml |
Entity-Graph → XML |
rw_xml_cache |
XML-Template-Cache |
xmltools |
XML-Hilfsfunktionen |
6.5 Statistik — src/statistik/
Sammelt und exportiert Regel-Statistiken:
| Klasse | Beschreibung |
|---|---|
rw_statistik |
Statistik-Sammler |
rw_statistikdata |
Statistik-Datencontainer |
rw_sinks |
Ausgabe-Sinks (CSV, etc.) |
7. Thread-Modell
flowchart TB
subgraph Threads["Thread-Modell"]
Main["Haupt-Thread<br/>(KVAI Host)"]
T1["Paket 1"]
T2["Paket 2"]
T3["Paket N"]
end
subgraph TLS["Thread-Local Storage"]
Sys["System::exemplar()<br/>(aktuelles Paket, Regelwerk, BHF)"]
Mem["gFallMemObject<br/>(1 MB Stack-Allokator)"]
LM["LeistungMerker::exemplar()"]
TOE["TaetigkeitOrtErmittler::exemplar()"]
end
Main --> T1
Main --> T2
Main --> T3
T1 --> Sys
T2 --> Sys
T3 --> Sys
T1 --> Mem
T2 --> Mem
T3 --> Mem
style Threads fill:#f0f0f0,stroke:#666,color:#333
style TLS fill:#2d2d44,stroke:#533483,color:#ccc
- Kein
thread_local→staticRueckbau: Diethread_local-Makros (MACRO_EMPTY_MENGE, System-Singletons) sind essenziell fuer parallele Paketverarbeitung. Jeder Thread hat seinen eigenen Entity-Graph und Speicher. - Paket-Isolation: Pakete werden parallel verarbeitet. Innerhalb eines Pakets laeuft alles single-threaded.
8. Build-System
flowchart LR
subgraph Source["Quellen"]
CPP["~230 .cpp"]
HPP["~450 .hpp"]
end
subgraph CMake["CMakeLists.txt"]
Core["rw_core<br/>(statische Bibliothek)"]
Host["rw_host<br/>(Executable, optional)"]
Tests["16 Test-Executables<br/>(optional)"]
end
subgraph Output["Output"]
Lib["librw_core.a"]
Bin["rw_host"]
TestBin["*_test"]
end
CPP --> Core
HPP --> Core
Core --> Lib
CPP --> Host
Host --> Bin
CPP --> Tests
Tests --> TestBin
style Source fill:#f0f0f0,stroke:#666,color:#333
style CMake fill:#2d2d44,stroke:#533483,color:#ccc
style Output fill:#0a3a0a,stroke:#51cf66,color:#51cf66
Die Quelldateien sind in sources.cmake ausgelagert um das CMakeLists.txt schlank zu halten.
Fuer Produktion wird rw_core als DLL (RW_DLL-Flag) gebaut.
9. Verzeichnisstruktur (vollstaendig)
| Verzeichnis | Inhalt | Dateien |
|---|---|---|
src/core/ |
RegelMaschine, Config, Init, exportierte API | 15 |
src/domain/ |
Entity-Klassen (Paket, Patientenfall, Leistung, …) | ~90 |
src/datatypes/ |
Container: Menge, Map, List, IntMenge |
~30 |
src/db/ |
Datenbank-Anbindung (Interface + Implementierungen) | 28 |
src/interface/ |
IRWLeistung, IRWSchein (Interface-Abstraktion) |
9 |
src/methods/ |
50+ Methoden (ab, ak, eb, fl, gs, ha, sb, st, …) | ~75 |
src/ur_meth/ |
25+ Ur-Methoden (komplexe Verfahrensanweisungen) | ~50 |
src/sb_meth/ |
6 SB-Methoden (Sonderbedingungen) | 11 |
src/rw_predicates/ |
87 Praedikate (Bedingungen) | ~80 |
src/rw_actions/ |
59 Aktionen (eine pro .hpp, Beanstanden, Streichen, Ersetzen) | 59 |
src/le/ |
Leistungserbringer-Subsystem (LANR, BSNR, Arztgruppen) | ~50 |
src/goae/ |
GOAE-Katalog-Subsystem (Farben, GOP-Vergleich) | ~40 |
src/statistik/ |
Statistik und Logging | 8 |
src/taetigkeitort/ |
Taetigkeit-Ort-Berechnung | ~5 |
src/json/ |
JSON-Parser und C++-Deserialisierung | 9 |
src/xml/ |
XML-Serialisierung (rw_smallxml) | 11 |
src/rest/ |
Host-Wrapper, Konstanten, Makros, Templates | ~34 |
src/util/ |
Tools: Datumsberechnung, Speicher, Kompression | ~50 |
src/zlib/ |
Statisch gelinkte ZLIB 1.2.3 | ~20 |
src/libs/ |
Vorkompilierte ZLIB-Binaries (HP-UX, Solaris, Win) | ~5 |
src/aktsource/ |
⚠️ Generierte Stammdaten (~100MB) | ~110 |
10. Beispiel: Ausfuehrungsfluss SB414
flowchart TD
subgraph SB414["SB414 — Mengenpruefung mit OPS-Filter"]
A["Eingabe: gm1 (GOP-Menge), opsm (OPS-Menge),<br/>anzahl (Mindestanzahl Tage), gm4, gm5"]
end
A --> B{"diff_lanr9?"}
B -->|"NO"| C["Pro Taetigkeit iterieren"]
B -->|"YES"| D["Einmalig BHZ-weit pruefen"]
C --> E
D --> E
E["Praedikat: SB314Praedikat"] --> F{"GOPs aus gm1<br/>vorhanden?"}
F -->|"NO"| X["return false"]
F -->|"YES"| G{"AKP-Pruefung<br/>(Arztgruppe, Kennzeichen,<br/>Alter, Geschlecht, ...)"}
G -->|"NO"| X
G -->|"YES"| H["Relevante Tage zaehlen<br/>(nicht in gm4, disjunkt zu gm5)"]
H --> I{"|relevante Tage| < anzahl?"}
I -->|"NO"| X
I -->|"YES"| J["return true → Aktion"]
J --> K{"Aktion: SB414Aktion"}
K --> L{"opsm leer?"}
L -->|"YES"| M["Alle gm1-Leistungen<br/>beanstanden"]
L -->|"NO"| N{"vertausche_opsm?"}
N -->|"YES"| O["Nur Leistungen MIT OPS<br/>in opsm beanstanden"]
N -->|"NO"| P["Nur Leistungen MIT OPS<br/>die opsm erfuellen"]
M --> Q["LeistungBeanstanden()"]
O --> Q
P --> Q
style SB414 fill:#1a1a2e,stroke:#e94560,color:#fff
style E fill:#16213e,stroke:#0f3460,color:#ccc
style J fill:#0a3a0a,stroke:#51cf66,color:#51cf66
style X fill:#3a0a0a,stroke:#ff6b6b,color:#ff6b6b
style Q fill:#0a3a0a,stroke:#51cf66,color:#51cf66
11. Wartung und Erweiterung
Neue Regel hinzufuegen
- Praedikat definieren: In
src/rw_predicates/einen neuen Funktor erstellen - Aktion definieren: Neue .hpp-Datei in
src/rw_actions/erstellen (besteht aus 59 Einzeldateien) - Regel registrieren: In den Stammdaten (XML/DB) die neue Regel mit Praedikat+Aktion+Methoden-Parametern eintragen
- Testfaelle: XML-Testdaten in
tests/sbXXX/ablegen
Aenderungen an bestehenden Regeln
- Immer
gitnexus_impactauf das Ziel-Symbol ausfuehren - Bei HIGH/CRITICAL Risk: Aenderung mit Fachbereich abstimmen
- Nach jeder Aenderung Build + Tests ausfuehren
gitnexus_detect_changes()vor Commit
12. Refactoring-Status (Juni 2026)
| Phase | Status | Beschreibung |
|---|---|---|
| 0 — Basis | ✅ abgeschlossen | Git-Init, UTF-8, unary_function → type-aliases, Boost→STL, Namespace maatini |
| 1 — C++11 | ✅ abgeschlossen | BOOST_FOREACH, boost::bind, boost::function1, thread_local, nullptr, override |
| 1 — rw_actions | ✅ abgeschlossen | Monolith → 59 Einzel-.hpp |
| — JSON | ✅ abgeschlossen | JSON-Parser + C++-Deserialisierung (src/json/, 9 Dateien) |
| 2 — C++14/17 | ✅ abgeschlossen | enum → enum class (4 Typen), auto für Iteratoren (24 Deklarationen) |
| 3 — Boost-Bereinigung | ✅ abgeschlossen | Nur bimap + lexical_cast verbleiben |
| 4 — Speicher | ✅ abgeschlossen | gFallMemObject explizit (10 no-arg copy() entfernt) |
| 5 — Sicherheit | ✅ abgeschlossen | Dangling-Pointer (25f9400), Thread-Safety (478062b, 5abfc85, ed4ba17), strcpy-Audit (a4aa685) |
| 6 — Cleanup | ✅ abgeschlossen | 6 tote Perl-Tools, kvai.ini (2003), leeres Verzeichnis gelöscht |
| 7 — Tests | 🔄 laufend | 23 Executables, 32+ standalone Prädikat-Tests, E2E-Pipeline, Catch2-Integration |
| 8 — Container | ⏳ geplant | CountList → unordered_map, IntMenge → set (optional) |
Siehe REFACTORING.md fuer Details.
Referenzen
- DOMAIN.md — Domänen-Glossar mit allen Abkuerzungen
- AGENTS.md — Verhaltensregeln fuer Coding Agents
- REFACTORING.md — Refactoring-Log und Planung
- SB414_Fachbeschreibung.md — Beispiel einer Fachbeschreibung
- sb414_flow.md — SB414 Ausfuehrungsfluss-Diagramm
- rw-interface/rw_interface.txt — XML-Schnittstellen-Beschreibung
- rw-interface/RW-Auftrag.xsd — XML-Schema Auftrag
- rw-interface/RW-Ergebnis.xsd — XML-Schema Ergebnis