V01 Erste Runs

This commit is contained in:
Christoph Schwörer
2026-08-26 07:34:29 +02:00
parent 0ec86aed8c
commit 18edae75b6
493 changed files with 170180 additions and 14 deletions
@@ -0,0 +1,382 @@
# Analysebericht
**System:** c-entron ERP-Suite (NEXOWARE c-entron ERP)
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse ohne Ausführung
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha` (`version.json`)
**Datum:** 2026-08-25
**Werkzeuge:** Dateisystem- und Volltextsuche, Quelltextlesung, `git log`. Keine Ausführung, keine
Datenbankverbindung, keine Agenten, keine MCP-Server.
---
## 1. Untersuchungsgegenstand und Vorgehen
### 1.1 Scope
Vorgegeben war die **gesamte Codebasis** ohne Modulbeschränkung. Der tatsächliche Umfang:
| Kennzahl | Wert |
|---|---|
| Projekte in `Centron.sln` | 44 |
| C#-Dateien (`.cs`) | 16 063 |
| XAML-Dateien | 1 233 |
| Razor-Komponenten | 491 |
| Ressourcendateien (`.resx`) | 14 (7 Sprachpaare) |
| Datenbank-Migrationsskripte (C#-Klassen) | 799 (Nummern bis 11820) |
| Markdown-Dokumentation unter `docs/` | 50 Dateien |
| Commits in der Historie | 52 135 |
| `.sql`-Dateien im Repository | 0 (Schema entsteht ausschließlich über Migrationsskripte) |
Bei diesem Umfang ist eine vollständige Zeile-für-Zeile-Analyse in einem Lauf ausgeschlossen. Die
Analysetiefe wurde daher **risikobasiert** priorisiert, entsprechend der Vorgabe des Auftrags:
Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen zuerst.
### 1.2 Durchlaufene Schritte der RRE-Methodenkette
| Schritt | Bearbeitung in diesem Lauf |
|---|---|
| 1 Scope | vorgegeben (gesamte Codebasis) |
| 2 Artefakterhebung | durchgeführt: Quellcode, Konfiguration (`nlog.config`, `appsettings.json`, `Directory.Build.props`, `version.json`, `global.json`), Ressourcen, Deployment (`docker/`, `deployment/`, `azure/`, `.github/workflows/`), Dokumentation (`docs/`, `README.md`, `CentronRights.md`), Change-Historie (`git log`) |
| 3 Technische Analyse | durchgeführt: Projektstruktur, Modulgliederung, Statusmaschinen (Beleg, Mahnstufe), Validierungs- und Berechtigungslogik, Persistenzpfade |
| 4 Semantische Interpretation | durchgeführt: Feld `Fakt` (Beobachtung) getrennt vom Feld `Aussage` (fachliche Soll-Aussage) |
| 5 Formalisierung | durchgeführt: 71 Anforderungen im vorgegebenen Format |
| 6 Traceability-Anreicherung | durchgeführt: 277 Artefaktbelege, Traceability-Matrix mit Vorwärts- und Rückwärtsabdeckung |
| 7 Validierung | **nicht** Teil dieses Laufs (manuell durch Fachexperten) |
---
## 2. Ergebnisumfang
| Ebene | Anforderungen |
|---|---|
| StRS | 15 |
| SyRS | 32 |
| SwRS | 24 |
| **Summe** | **71** |
### Belegverteilung
| Belegklasse | StRS | SyRS | SwRS | Summe | Anteil |
|---|---|---|---|---|---|
| `PRIMÄR` | 33 | 86 | 55 | 174 | 62,8 % |
| `SEKUNDÄR` | 14 | 25 | 22 | 61 | 22,0 % |
| `KONTEXT` | 13 | 17 | 12 | 42 | 15,2 % |
| **Summe** | 60 | 128 | 89 | **277** | 100 % |
Durchschnittlich 3,9 Belege je Anforderung. **Jede der 71 Anforderungen trägt mindestens einen
`PRIMÄR`-Beleg**; die für Sicherheit, Fakturierung und Berechtigungen verschärfte Evidenzanforderung ist
damit für alle betroffenen Anforderungen erfüllt.
### Statusverteilung
| Status | Anzahl |
|---|---|
| `belegt` | 53 |
| `belegt; Workaround` | 18 |
| `HYPOTHESE` | 0 |
Die 18 als `Workaround` markierten Anforderungen beschreiben erkennbare historische Sonderfälle oder
technische Altlasten (u. a. ungesalzene Kennworthashes, doppelter Persistenzpfad, dreifache
Intervallumrechnung, externe Skriptnummernvergabe) und sind bei der Validierung vorrangig zu prüfen.
---
## 3. Modul- und Komponentenübersicht mit Analysetiefe
Legende der Tiefenstufen:
**A = tief** (Kernquelltexte gelesen, Regeln zeilenscharf belegt) ·
**B = mittel** (Schlüsselstellen gelesen, Struktur und Statusmaschinen erfasst) ·
**C = flach** (Struktur, Namensgebung, Enums, Dateiinventar erfasst) ·
**D = nicht analysiert**
### 3.1 Backend (`src/backend/`)
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Administration/Rights` (`AppRightsBL`) | **A** | vollständig gelesen (859 Zeilen); Rechtemodell, Gruppenschutz, Protokollierung, Cache |
| `Administration/Logins/Auth` | **A** | `Authenticator`, `BasicAuthenticator`, `AuthenticatorFactory`, `WebAccountAuthenticator` vollständig gelesen |
| `Administration/Logins` (`TicketBL`, `WebAccountBL`) | **A** | `TicketBL` vollständig; `WebAccountBL` Anmeldepfad |
| `Administration/Logins/TwoFactor` | **B** | `TwoFactorAuthBL` Entscheidungslogik gelesen; Validatoren nur inventarisiert |
| `Administration/Licensing` (`LicenseManager`) | **A** | vollständig gelesen (412 Zeilen) |
| `Administration/AccessTokens` | **B** | Validierung, Erzeugung, Hashing, Lizenzbegrenzung gelesen |
| `Administration/Company` (`NumberGroupBL`) | **A** | vollständig gelesen |
| `Administration/Scripts` (`ScriptEngineBL`) | **B** | Engine bis Z. 130 gelesen; 2 von 799 Skripten stichprobenartig |
| `Administration/DataSecurity`, `.../Documents/Dsgvo` | **B** | Rechteprüfung, Statistikermittlung, Vertragsverwaltung gelesen |
| `Administration/Settings` | **C** | über Nutzungsstellen und Dokumentation erschlossen |
| `Sales/Receipts` (`ReceiptBL`, 11 441 Zeilen) | **B** | gezielt gelesen: Statusübergänge, Rechteprüfmethoden, ZUGFeRD-Bedingung, Protokollierung, Nummernkreis. Ca. 15 % des Umfangs |
| `Sales/Receipts/Invoices/InvoiceSpecificLogic` | **A** | vollständig gelesen (803 Zeilen) |
| `Sales/Receipts/Invoices/Dunning` | **B** | Statusmaschine, Lauf und Rücknahme gelesen |
| `Sales/CustomerAssets/AutomaticFactura` (6 101 Zeilen) | **B** | Intervallumrechnung, Kontingentbuchung, Intervallbeginn gelesen. Ca. 10 % |
| `Sales/Support` (Helpdesk, ca. 50 Klassen) | **B** | `HelpdeskCloseBL`, `HelpdeskTimerBL`, `UpdateHelpdeskBL` (Ausschnitte) |
| `Sales/Customers`, `Accounts`, `BusinessPartner` | **C** | Struktur erfasst |
| `Warehousing` (Artikel, Lager, Barcode, Preise) | **C** | Struktur und Klassennamen erfasst |
| `EDI` (8 Lieferantenformate) | **C** | Enums und Verzeichnisstruktur erfasst; keine Parserlogik gelesen |
| `Finances`, `Accounting` | **C** | Struktur erfasst |
| `Centron.Entities` (`ReceiptBase`, Basisklassen) | **B** | Belegbasis und Schlüsselkonventionen gelesen |
| `Centron.DAO` (Mappings) | **B** | Beispielhaft `RechKopfMaps`, `ReceiptInvoiceMaps`, `ReceiptInvoiceVersionMaps`, `CentronChecklistBaseMaps` |
| `Centron.Interfaces` (Enums, Results, CalculationUtils) | **A** | `CentronObjectKindNumeric`, `ReceiptState`, `ApplicationKind`, `BillingIntervalKinds`, `EdiDataType`, `EDILogState`, `DefaultMessageCodes`, `ResultStatus`, `CalculationUtils` vollständig |
| `Centron.BL` - übrige ca. 60 Fachbereiche | **D** | siehe Abschnitt 5 |
### 3.2 Web-Service (`src/webservice/`)
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Centron.Host` Interception (`AuthenticateInterceptor`) | **A** | vollständig gelesen |
| `Centron.Controllers` Autorisierungsattribute | **C** | Dateiinventar; Inhalte nicht gelesen |
| `Centron.Controllers` REST-Controller (ca. 40) | **C** | Inventar erfasst |
| `Centron.WebServices.Core` (2 530 Dateien, DTOs) | **C** | gezielt: `UserRightsConst`, EDI-Enums, `LoginRequest` |
| `Centron.Host.WindowsService` / `.Console` | **B** | Konfigurationen gelesen |
### 3.3 Clients
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| `Centron.WPF.UI` (5 255 Dateien) | **C** | `ModuleRegistration.cs` (84 Module) und Modulverzeichnisstruktur; keine ViewModels gelesen |
| `CentronNexus` (762 Dateien, 460 Razor) | **C** | Bereichsstruktur (WebCart, WebOffer, ServiceBoard, DocumentSigning, Management); keine Komponenten gelesen |
| `CentronNexus.OutlookAddIn` | **D** | nur Existenz erfasst |
| `Centron.Controls` (880 Dateien) | **D** | nur Existenz und Ressourcen erfasst |
### 3.4 Querschnitt
| Bereich | Tiefe | Bearbeitung |
|---|---|---|
| Build/Versionierung (`Directory.Build.props`, `version.json`, `global.json`) | **A** | vollständig gelesen |
| Deployment (`docker/`, `deployment/`) | **B** | `Dockerfile`, `appsettings.json` gelesen; WixSharp-Installer nur inventarisiert |
| CI/CD (`.github/workflows/`, `azure/`) | **C** | `tests.yml` und `build.yml` (Kopfteile) gelesen |
| Protokollierung (`nlog.config` × 3, `appsettings.json`) | **A** | Windows-Dienst-Konfiguration vollständig |
| Tests (`tests/`, 12 Projekte) | **C** | Inventar und CI-Matrix erfasst; keine Testfälle gelesen |
| Externe Konnektoren (`src/apis/`: GLS, Shipcloud, eBInterface, ITscope, Icecat, FinAPI, COP, EGIS) | **C** | Inventar erfasst |
| Change-Historie | **B** | `git log` der letzten 200 Commits ausgewertet; Ticketreferenzen als `KONTEXT`-Belege verwendet |
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde nach Fertigstellung der drei Spezifikationsdokumente maschinell über die erzeugten
Dateien ausgeführt.
### 4.1 Doppelte oder mehrfach vergebene IDs
**Ergebnis: keine Befunde.**
| Datei | Anforderungen | Doppelte IDs |
|---|---|---|
| `StRS.md` | 15 | 0 |
| `SyRS.md` | 32 | 0 |
| `SwRS.md` | 24 | 0 |
Die IDs sind je Ebene lückenlos fortlaufend (StRS-001…015, SyRS-001…032, SwRS-001…024).
### 4.2 Anforderungen ohne Beleg
**Ergebnis: keine Befunde.** Alle 71 Anforderungen führen mindestens einen Beleg, und alle 71 führen
mindestens einen `PRIMÄR`-Beleg. Die verschärfte Evidenzanforderung für Sicherheit, Fakturierung und
Berechtigungen ist damit erfüllt; keine Anforderung musste deswegen als `[HYPOTHESE]` markiert werden.
### 4.3 Tracelinks auf nicht existierende IDs
**Ergebnis: keine Befunde.** 67 eindeutige IDs werden in den `Tracelinks`-Feldern referenziert; alle 67
sind definiert. Es existiert kein Verweis ins Leere.
**Nebenbefund - asymmetrische Verweise:** Vier SwRS-IDs werden in den `Tracelinks`-Feldern der
SyRS-Anforderungen nicht genannt, obwohl sie ihrerseits auf eine SyRS-Anforderung verweisen:
| SwRS-ID | verweist auf | wird von dort nicht zurückverwiesen |
|---|---|---|
| SwRS-004 (Zweischichtiges DB-Schema) | SyRS-001, SyRS-026 | ja |
| SwRS-006 (Schlüsselkonvention I3D) | SyRS-001 | ja |
| SwRS-018 (Modulregistrierung) | SyRS-006, SyRS-014, SyRS-032 | ja |
| SwRS-019 (Einstellungsverwaltung) | SyRS-016, SyRS-024 | ja |
Weitere Asymmetrien betreffen SwRS-002 → SyRS-006, SwRS-003 → SyRS-001, SwRS-007 → SyRS-026,
SwRS-012 → SyRS-024 und SwRS-013 → SyRS-003.
**Behandlung:** In `Traceability.md` wurde die **symmetrische Hülle** beider Richtungen gebildet und als
maßgebliche Relation ausgewiesen. Die Rückwärts-Traceability (SwRS → SyRS → StRS) ist damit lückenlos, die
Vorwärts-Traceability (StRS → SyRS → SwRS) über die Abdeckungsmatrizen in `Traceability.md`,
Abschnitte 2 und 3, ebenfalls. Fachlich ist keine Anforderung unverbunden.
### 4.4 Vollständigkeit der Pflichtfelder
**Ergebnis: keine Befunde.** Alle zwölf Pflichtfelder (`Titel`, `Ebene`, `Typ`, `Akteur`,
`Vorbedingung`, `Fakt`, `Aussage`, `Ergebnis`, `Prüfidee`, `Tracelinks`, `Konsolidierung`, `Status`) sind
in allen 71 Anforderungen belegt (jeweils 71 Vorkommen).
### 4.5 Abdeckung
- Alle 15 StRS-Anforderungen sind durch mindestens eine SyRS-Anforderung abgedeckt.
- Alle 32 SyRS-Anforderungen sind durch mindestens eine SwRS-Anforderung konkretisiert.
- Alle 24 SwRS-Anforderungen verweisen auf mindestens eine existierende SyRS-Anforderung.
### 4.6 Konsolidierungsbefunde
19 Konsolidierungskandidaten wurden identifiziert und in `Traceability.md`, Abschnitt 5, als
Redundanzregister (K-01…K-19) zusammengefasst. Die gewichtigsten:
| Nr. | Redundanz | Bewertung |
|---|---|---|
| K-08 | Doppelimplementierung jeder Modulschnittstelle (`BL*Logic` / `WS*Logic`) | größte strukturelle Redundanz; entfällt in der Zielarchitektur vollständig |
| K-06 | Belegpersistenz über modernes View-Mapping **und** Legacy-Save-Repository | häufigste Fehlerquelle laut Entwicklerdokumentation |
| K-01 | Vier Mechanismen zur Rechteprüfung | Sicherheitsrelevant: unterschiedliche Cache-Semantik |
| K-02 | Drei Implementierungen der Ticketabschluss-Prüfung, davon eine wirkungslos | Prozessintegrität, siehe H-03 |
| K-03 | Drei Implementierungen der Intervallumrechnung mit abweichender `Daily`-Behandlung | Fakturierungsrelevant, siehe H-02 |
| K-04 | Vier Auslöser für den Belegübergang nach "abgeschlossen" | erschwert eine belastbare Statusmaschine |
| K-07 | Drei Hashverfahren nebeneinander | Sicherheitsrelevant, siehe SwRS-009 |
---
## 5. Bekannte Lücken
| Nr. | Lücke | Auswirkung |
|---|---|---|
| L-01 | **Delphi-Altsystem nicht im Arbeitsverzeichnis.** `LicenseManager.TryFixCentronDelphiVersionNumber()` und der Kommentar in `CentronObjectKindNumeric.cs` belegen ein aktiv genutztes Delphi-System (Version 9.3.x) auf derselben Datenbank und mit derselben Lizenz-GUID. | Fachfunktionen, die ausschließlich dort implementiert sind, fehlen in dieser Spezifikation vollständig. Siehe H-08. |
| L-02 | **Kein Datenbankschema als Artefakt.** Es existieren null `.sql`-Dateien; das Schema entsteht ausschließlich zur Laufzeit aus 799 Migrationsskripten. | Constraints, Indizes, Trigger, Views und Default-Werte konnten nicht als `PRIMÄR`-Belege herangezogen werden. Alle datenbezogenen Anforderungen stützen sich auf Mappings, Konventionen und Skripte. |
| L-03 | **EDI-Verarbeitungslogik nicht gelesen.** Nur Enums und Verzeichnisstruktur erfasst. | Die konkreten Feldzuordnungen, Validierungen und Fehlerbehandlungen je Lieferant fehlen. |
| L-04 | **Oberflächenlogik der Clients nicht gelesen.** 5 255 WPF-Dateien und 460 Razor-Komponenten wurden nur strukturell erfasst. | Validierungen und Pflichtfeldregeln, die ausschließlich in ViewModels bzw. Komponenten implementiert sind, fehlen. |
| L-05 | **Testprojekte nicht ausgewertet.** 12 Testprojekte (BL, DAO, Core, Controls, Integration, End-to-End, Nexus, Playwright, 4 API-Testprojekte). | Tests sind eine hochwertige Quelle für erwartetes Fachverhalten; dieses Potenzial ist ungenutzt. |
| L-06 | **Rechteverwendung nicht analysiert.** 750 Rechtekonstanten; keine Verwendungsanalyse über alle 16 063 Dateien. | Der produktiv relevante Rechteumfang ist unbekannt. Siehe H-11. |
| L-07 | **Fachbereiche ohne jede Anforderung.** Lagerwirtschaft/Inventur, Produktion/PLM, Kassenbuch, Online-Banking/Zahlungsverkehr, CRM-Kampagnen, Projektmanagement, Asset-/Inventarmanagement (Riversuite/DocuBoard), TAPI-Telefonie, Reportengine, Mailscanner/Mailversand, Kalender/Exchange-Synchronisation, Statistik/Dashboards, KI-Chat-Modul, Umfragen, RMA, Provisionsabrechnung, Leasing, Checklistenverwaltung, Task-/Prozessmanagement, Passwortmanager, Videoportal, SEPA/Lastschrift. | Schätzungsweise 55-65 % des Fachumfangs sind nicht spezifiziert. |
| L-08 | **Change-Historie nur stichprobenartig.** 200 von 52 135 Commits ausgewertet. | Historische Begründungen für Sonderfälle blieben weitgehend ungehoben. |
---
## 6. Selbstbewertung
### 6.1 Vollständig analysierte Module
Als **vollständig** (Tiefe A) gelten:
`AppRightsBL`, `Authenticator`/`BasicAuthenticator`/`AuthenticatorFactory`/`WebAccountAuthenticator`,
`TicketBL`, `LicenseManager`, `NumberGroupBL`, `InvoiceSpecificLogic`, `CalculationUtils`,
`AuthenticateInterceptor`, `SHA1Decoder`, `CryptoUtils`, sowie die zentralen Enums und Wertetypen
(`CentronObjectKindNumeric`, `ReceiptState`, `ApplicationKind`, `BillingIntervalKinds`, `EdiDataType`,
`EDILogState`, `DefaultMessageCodes`, `ResultStatus`, `CentronConnectionType`).
Diese Auswahl deckt die vom Auftrag priorisierten Risikobereiche - **Sicherheit, Berechtigungen und die
Kernregeln der Fakturierung** - ab.
### 6.2 Stichprobenhaft analysierte Module
Tiefe B: `ReceiptBL` (ca. 15 %), `AutomaticFacturaBL.Contracts` (ca. 10 %), `DunningBL`/`DunningRunBL`,
`HelpdeskCloseBL`/`HelpdeskTimerBL`/`UpdateHelpdeskBL`, `TwoFactorAuthBL`, `AccessTokenBL`,
`ScriptEngineBL`, `DataSecurityBL`/`DsgvoBL`, DAO-Mappings, Entitätsbasisklassen, Deployment.
### 6.3 Nicht analysierte Module
Siehe L-07. Der Anteil nicht spezifizierter Fachbereiche wird auf 55-65 % geschätzt (Grundlage: 84
registrierte UI-Module gegenüber 15 fachlich abgedeckten Bereichen; ca. 60 BL-Fachverzeichnisse gegenüber
ca. 12 bearbeiteten).
### 6.4 Stellen mit dünner Beleglage
Der `PRIMÄR`-Anteil liegt insgesamt bei 62,8 %. Überdurchschnittlich viele `SEKUNDÄR`- und
`KONTEXT`-Belege - und damit die dünnste Beleglage - weisen auf:
| Anforderung | Beleglage | Ursache |
|---|---|---|
| StRS-015 / SyRS-031 (Betriebsformen) | 2 `PRIMÄR`, 1 `SEKUNDÄR`, 1 `KONTEXT` je Anforderung | Betriebsverhalten ist nur aus Konfiguration ableitbar, nicht aus durchgesetzter Logik |
| SyRS-021 (EDI-Formate) | Enums `PRIMÄR`, Abdeckungsgrad je Lieferant nur `KONTEXT` | Parserlogik nicht gelesen (L-03) |
| StRS-014 / SyRS-028 (Mehrsprachigkeit) | Ressourcendateien `PRIMÄR`, Vollständigkeit nicht geprüft | Kein Abgleich der Schlüsselmengen durchgeführt |
| SwRS-006 / SwRS-007 (Schlüssel- und Auditspalten) | Konventionsdokument als `PRIMÄR` gewertet, Schema selbst nicht prüfbar | L-02 |
| StRS-005 (Helpdesk) | Umfangsargument über Verzeichnisinventar | Nur 3 von ca. 50 Helpdesk-Klassen gelesen |
| StRS-009 (Beschaffung/EDI) | Belegarten `PRIMÄR`, Prozessablauf `KONTEXT` | L-03 |
Methodisch relevant: **Die Entwicklerdokumentation unter `docs/` wurde durchgängig nur als `KONTEXT`
klassifiziert und nie als alleiniger Beleg verwendet.** Der Grund ist ein konkreter Widerspruch zum Code
(`receipts-backend-architecture.md` beschreibt vier Belegzustände, der Code kennt drei) - siehe H-07. Das
hat den `PRIMÄR`-Anteil gesenkt, die Belastbarkeit der Spezifikation aber erhöht.
### 6.5 Was in einer Folge-Iteration nachzuholen ist
Priorisierte Empfehlungen:
**Priorität 1 - Klärung offener Risiken (blockierend für die Zielarchitektur)**
1. **Delphi-Altsystem abgrenzen** (H-08, L-01): ohne diese Klärung ist der Migrationsumfang unbestimmt.
2. **Testprojekte auswerten** (L-05): 12 Testprojekte sind die verlässlichste ungenutzte Quelle für
erwartetes Fachverhalten - insbesondere `Centron.Tests.EndToEnd`, das laut Belegdokumentation die
Datenbankskripte ausführt und Rohtabellenwerte prüft. Erwarteter Nutzen: hoher Zuwachs an
`PRIMÄR`-Belegen bei geringem Aufwand.
3. **Datenbankschema rekonstruieren** (L-02): durch Auswertung aller 799 Migrationsskripte ließe sich das
Zielschema mit Constraints und Indizes ableiten, ohne die Datenbank zu betreiben.
**Priorität 2 - Abdeckung der Fachbreite**
4. **Lagerwirtschaft und Bestandsführung**, **Zahlungsverkehr/Online-Banking**, **Provisionsabrechnung**
und **Kassenbuch** ausarbeiten - alle vier sind abrechnungsrelevant und unterliegen damit derselben
verschärften Evidenzanforderung wie die bereits bearbeiteten Bereiche.
5. **`ReceiptBL` systematisch erschließen** (11 441 Zeilen, bisher ca. 15 %): die verbleibenden 85 %
enthalten mit hoher Wahrscheinlichkeit weitere durchgesetzte Geschäftsregeln.
6. **EDI-Verarbeitung je Lieferant** (L-03) und die **ZUGFeRD-Feldzuordnung** gegen die vorhandenen
Zuordnungsdokumente prüfen.
**Priorität 3 - Methodische Vertiefung**
7. **Rechteverwendungsanalyse** über alle 16 063 Dateien (L-06), um den produktiv relevanten
Rechteumfang zu bestimmen.
8. **Oberflächenvalidierungen** aus ViewModels und Razor-Komponenten heben (L-04) - dort liegen
erfahrungsgemäß Pflichtfeld- und Plausibilitätsregeln, die serverseitig fehlen.
9. **Erweiterte Commit-Analyse** (L-08): gezielte Suche nach Commits zu den 18 als `Workaround`
markierten Stellen, um deren historische Begründung zu belegen.
### 6.6 Bewertung der Ergebnisqualität
**Stärken dieses Laufs**
- Vollständige Belegpflicht eingehalten: 71 von 71 Anforderungen mit `PRIMÄR`-Beleg, keine unbelegte
Soll-Aussage.
- Konsequente Trennung von `Fakt` und `Aussage`, dadurch ist jede Interpretation für den Fachexperten
überprüfbar.
- Konsistenzcheck ohne Befund bei IDs, Belegen und Tracelinks.
- 19 konkrete Konsolidierungskandidaten mit Fundstellen - unmittelbar verwertbar für den
Architekturentwurf des Zielsystems.
- 18 identifizierte Altlasten/Sonderfälle mit Migrationsrelevanz.
**Schwächen dieses Laufs**
- **Die Fachbreite ist die größte Schwäche.** Etwa 55-65 % des Fachumfangs sind nicht spezifiziert. Die
vorliegende Spezifikation ist als Basis für eine Neuimplementierung **noch nicht ausreichend**; sie
deckt Sicherheit, Berechtigungen und den Kern der Belegverarbeitung ab, nicht aber die Fachbreite.
- Der Detaillierungsgrad ist ungleich: `InvoiceSpecificLogic` ist zeilenscharf erfasst, die
gleichrangigen Logiken der übrigen sechs Kundenbelegarten sind es nicht. Das birgt die Gefahr, dass
belegartspezifische Abweichungen unentdeckt bleiben.
- Die Prüfideen sind konzeptionell formuliert und nicht gegen ausführbare Testfälle validiert.
- Nichtfunktionale Anforderungen sind gegenüber funktionalen unterrepräsentiert (5 von 71 explizit einem
ISO/IEC-25010-Merkmal zugeordnet, weitere implizit). Insbesondere zu Performance-Effizienz,
Skalierbarkeit und Lastverhalten liegen kaum Artefaktbelege vor - ein für eine SaaS-Zielarchitektur
wesentlicher blinder Fleck.
**Einschätzung der Reife:** Die Spezifikation ist für die abgedeckten Bereiche belastbar und
validierungsfähig. Für die vollständige Ablösung des Altsystems sind nach heutiger Einschätzung
mindestens drei bis vier weitere Iterationen entlang der Prioritäten in Abschnitt 6.5 erforderlich.
---
## 7. Randbedingungen - Einhaltung
| Vorgabe | Einhaltung |
|---|---|
| Keine Halluzinationen; nicht Belegbares offenlegen | eingehalten - jede Anforderung mit `PRIMÄR`-Beleg; Nicht-Belegbares in `Hypothesen.md` (11 offene Fragen) und Abschnitt 5 (8 Lücken) |
| Keine Generierung von Code | eingehalten - ausschließlich Spezifikationsartefakte erzeugt |
| Keine Annahme nicht vorhandener Tools | eingehalten - ausschließlich Dateisystemsuche, Quelltextlesung und `git log` verwendet |
| Migrationsperspektive (Workarounds kennzeichnen) | eingehalten - 18 Anforderungen mit `Status: belegt; Workaround` |
| Sprache Deutsch, technische Bezeichner im Original | eingehalten |
| Codebasis nur lesen, nicht verändern | eingehalten - siehe Abschnitt 8 |
---
## 8. Nachweis der Unverändertheit der Codebasis
Der Arbeitsbereich `C:\DEV\MasterArbeit\QuellCode\CentronERP` wurde ausschließlich lesend verwendet.
Sämtliche Ergebnisdateien wurden nach
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\Ergebnisse\`
geschrieben. Der Git-Status der Codebasis war zu Beginn des Laufs sauber (`clean`) und wurde nicht durch
schreibende Operationen berührt.
---
## 9. Erzeugte Artefakte
| Datei | Inhalt |
|---|---|
| `StRS.md` | 15 Stakeholder-Anforderungen, Systemüberblick, Stakeholderliste |
| `SyRS.md` | 32 Systemanforderungen (27 funktional, 5 explizit nicht-funktional nach ISO/IEC 25010) |
| `SwRS.md` | 24 Softwareanforderungen (Architektur, Datenmodell, Sicherheitsmechanismen, Berechnungsregeln) |
| `Traceability.md` | Haupttabelle, zwei Abdeckungsmatrizen, Redundanzregister K-01…K-19 |
| `Hypothesen.md` | 11 offene Fragen mit fehlender Information und Priorisierung |
| `Glossar.md` | Domänen- und Systembegriffe mit Fundstellen |
| `Analysebericht.md` | dieses Dokument |
@@ -0,0 +1,404 @@
# Glossar
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
Das Glossar definiert die in `StRS.md`, `SyRS.md` und `SwRS.md` verwendeten Domänen- und Systembegriffe.
Jeder Eintrag nennt die Fundstelle, aus der die Bedeutung abgeleitet wurde. Technische Bezeichner
(Klassen, Methoden, Spalten) sind in ihrer Originalsprache belassen.
---
## A
**Abholschein** (`PickupListClass = 5`, Tabellen `AbholKopf`/`AbholPos`, View `PickupLists`)
Kundenbeleg, mit dem Waren zur Abholung durch den Kunden bereitgestellt werden. Eine der sieben
Kundenbelegarten.
*Beleg:* `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 41-42.
**Access-Token**
Langlebiges, widerrufbares Zugangsmerkmal für den API-Zugriff durch Fremdsysteme, alternativ zum
Sitzungsticket. 48 Zeichen, gespeichert als SHA-256-Hash, optional befristet.
*Beleg:* `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs`.
**AnlageArt**
Numerischer Schlüssel der Belegart in der gemeinsamen Protokolltabelle `AnlageLog`; entspricht den Werten
aus `CentronObjectKindNumeric` (1 = Angebot … 22 = Vertrag).
*Beleg:* `docs/reference/receipts/receipts-backend-architecture.md`, Abschnitt "AnlageArt Values".
**Angebot** (`OfferClass = 1`, Tabellen `AngKopf`/`AngPos`, View `Offers`)
Unverbindliches Leistungsangebot an einen Kunden; Ausgangspunkt der Belegkette.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 23-24.
**AppGroup** (Tabelle `Sichgrup`)
Rechtegruppe. Rechte werden ausschließlich Gruppen zugewiesen, Benutzer erhalten Rechte über die
Gruppenmitgliedschaft. Die Gruppe "Administratoren" (I3D 6) ist gegen Löschung geschützt.
*Beleg:* `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 348-374.
**AppUser** (Tabelle `Sichbenu`)
Mitarbeiterkonto zur Anmeldung am System. Verknüpft mit einem `Employee` (Personalstamm) und über
`AppUserMember` (`Sichmemb`) mit Rechtegruppen.
*Beleg:* `AppRightsBL.cs` Z. 95-111; `Authenticator.cs` Z. 157-218.
**ApplicationKind**
Anmeldefähige Anwendung (z. B. "NEXOWARE c-entron ERP", "c-entron Nexus", "Outlook Add-In",
"Service-Board"). Trägt eine Lizenz-GUID, eine Ablaufart (`ExpirationKind`), eine Nutzungsart
(`LicenseUsageKind`) sowie optional ein erforderliches (`RequiredRight`) und ein ausschließendes Recht
(`DisallowingRight`). 44 Anwendungen sind definiert.
*Beleg:* `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs`.
**Auftrag** (`OrderClass = 2`, Tabellen `AufKopf`/`AufPos`, View `Orders`)
Verbindliche Kundenbestellung; entsteht typischerweise aus einem Angebot.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 25-26.
---
## B
**Beleg** (engl. *Receipt*)
Sammelbegriff für die kaufmännischen Geschäftsobjekte mit Kopf- und Positionsdaten. Unterschieden werden
**Kundenbelege** (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag) und
**Lieferantenbelege** (Anfrage, Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift).
*Beleg:* `CentronObjectKindNumeric.IsCustomerReceipt()` / `IsSupplierReceipt()`.
**Belegkopf** (`*Kopf`)
Kopfdatensatz eines Belegs mit Nummer, Datum, Version, Status, Kunde, Adressen, Währung und Audit-Feldern.
*Beleg:* `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs`.
**Belegposition** (`*Pos`)
Positionsdatensatz eines Belegs mit Artikel, Menge, Preis, Rabatt, Steuersatz und Positionsnummer.
*Beleg:* `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptItemBase.cs`.
**Belegstatus** (`ReceiptState`)
Zustand eines Belegs: `Active` = 1 ("offen"), `Completed` = 2 ("abgeschlossen"), `Canceled` = 3
("storniert").
*Beleg:* `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs`.
**Belegversion** (`*Versions`-Tabellen)
Unveränderlicher Abzug einer früheren Belegfassung (Kopf und Positionen) in einer strukturgleichen
Versionstabelle, referenziert über `OriginalI3D`.
*Beleg:* `src/backend/Centron.DAO/Mappings/Sales/Receipts/Invoices/ReceiptInvoiceVersionMaps.cs`.
**Belegweiterführung** (engl. *forwarding*)
Erzeugung eines Folgebelegs aus einem bestehenden Beleg unter Übernahme von Positionen und Steuersätzen.
Die zulässigen Quell- und Zielarten sind je Belegart festgelegt.
*Beleg:* `InvoiceSpecificLogic.CanBeForwardedFrom()` / `CanBeForwardedInto()`.
**Bestellung** (`SupplierOrder = 7`)
Lieferantenbeleg zur Beschaffung von Waren oder Leistungen.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 140-141.
---
## C
**c-entron.NET**
Der Windows-Rich-Client der Suite (WPF/XAML, DevExpress). Kann wahlweise direkt gegen die Datenbank oder
über den Web-Service betrieben werden.
*Beleg:* `src/centron/Centron.WPF.UI`; `CentronConnectionType`.
**c-entron Nexus** (auch "c-entron Web")
Die webbasierte Anwendung auf Blazor-Basis mit den Bereichen WebCart (Shop), WebOffer (Angebotsannahme),
ServiceBoard (Ticketsicht), DocumentSigning (digitale Unterschrift) und Management.
*Beleg:* `src/nexus/CentronNexus`; `README.md`.
**CentronObjectKindNumeric**
Systemweites Enum, das jedem Fachobjekttyp einen stabilen numerischen Schlüssel zuweist. Werte ab
7 600 000 sind für Neuanlagen aus dem .NET-System reserviert; bestehende Werte dürfen nicht geändert
werden.
*Beleg:* `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 6-14.
**Checkliste** (`CentronChecklist`, `Checklist = 7600082`)
Aufgabenliste an einem Fachobjekt (u. a. am Ticket). Das Kennzeichen `CanCloseHelpdesk` steuert, ob ein
Ticket bei offenen Punkten dieser Checkliste abgeschlossen werden darf.
*Beleg:* `src/backend/Centron.DAO/Mappings/CheckListArea/CentronChecklistBaseMaps.cs` Z. 30.
**ConcurrencyControlGuid**
GUID-Feld jedes Belegs zur optimistischen Sperre. Weicht der vom Client übergebene Wert vom gespeicherten
ab, wird das Speichern mit dem Code `ChangedByOtherInstance` (10009) abgelehnt.
*Beleg:* `ReceiptBase.cs` Z. 55; `ReceiptBL.cs` Z. 4939-4940.
**Kontingent** (`Contingent`)
Vertraglich vereinbartes Leistungsvolumen (in Stunden oder Geldbetrag), gegen das erbrachte Leistungen
gebucht werden. Kennt Überbuchung (`Overbooking`), Restmitnahme (`TakeRest`), Restwert
(`ContingentResidualValue`) und Limitabrechnung (`IsContingentLimitBilling`).
*Beleg:* `ReceiptBL.WriteReceiptLogs()`; `AutomaticFacturaBL.Contracts.StoreBookedContingent()`.
---
## D
**DAOSession**
Datenbanksitzung auf NHibernate-Basis. Trägt einen Sitzungscache, in dem u. a. die Rechteliste eines
Benutzers zwischengespeichert wird.
*Beleg:* `src/backend/Centron.DAO/DAOSession.cs`; `src/backend/Centron.DAO/SessionCache.cs`.
**DBUpdate**
Tabelle, in der die bereits ausgeführten Datenbank-Migrationsskripte anhand ihrer Skriptnummer vermerkt
sind.
*Beleg:* `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs`.
**Einschränkendes Recht** (engl. *restricting right*)
Recht mit invertierter Wirkung: Sein Vorhandensein **beschränkt** den Benutzer, statt ihm etwas zu
erlauben (z. B. "Tickets anzeigen - nur eigene", "Rechnungen anzeigen - nur eigene Filiale").
*Beleg:* `CentronRights.md`; `AppRightsBL.GetAssignableAdminRightI3Ds()`.
**Distributor / Distri**
Großhändler, mit dem elektronisch Belege ausgetauscht werden (ALSO, Alltron, Herweck, Komsa u. a.).
*Beleg:* `src/backend/Centron.BL/EDI/`; `EdiDataType`.
**DSGVO-Modul**
Funktionsbereich zur Unterstützung datenschutzrechtlicher Pflichten: Verwaltung von
Auftragsverarbeitungsverträgen (`OrderProcessingContract`), Auswertung löschbarer Altdatenbestände und
Löschung personenbezogener Kontaktdaten.
*Beleg:* `src/backend/Centron.BL/Administration/Documents/Dsgvo/`;
`src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs`.
---
## E
**EDI** (Electronic Data Interchange)
Elektronischer Belegaustausch mit Lieferanten in strukturierten Formaten. Unterstützte Formate:
OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron, ZUGFeRD. Ausgetauschte Dokumentarten: Bestellung,
Bestellbestätigung, Lieferschein, Rechnung.
*Beleg:* `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs`,
`EDIConnectionObjectKind.cs`.
**Employee** (Personalstamm, Tabelle `Personal`)
Mitarbeiterdatensatz. Trägt u. a. die Filialzuordnung (`BranchI3D`), Einstellungs- und Austrittstermin,
die für die Anmeldefähigkeit ausgewertet werden.
*Beleg:* `Authenticator.ValidateAppUser()` Z. 206-216.
**ExpirationKind**
Ablaufart eines Sitzungstickets je Anwendung: `Default` (30 Minuten), `MonitoringConnector` (5 Minuten),
`FromSettings` (konfigurierbar, mindestens 30 Minuten), `OneDay` (1440 Minuten).
*Beleg:* `ApplicationKind.cs` Z. 165-171; `TicketBL.GetExpireDate()`.
---
## F
**Filiale** (`Branch`, `BranchI3D`)
Organisatorische Untereinheit eines Mandanten. Belege, Rechtegruppen und Nummernkreise können
filialbezogen geführt werden. Ein fehlender oder auf 0 gesetzter Wert gilt als Hauptfiliale.
*Beleg:* `ReceiptBL.CanUserCreateReceiptsInBranch()` Z. 10260-10265.
---
## G
**Gutschrift** (`CreditVoucherClass = 6`, Tabellen `GutKopf`/`GutPos`, View `CreditVouchers`)
Kundenbeleg zur Rückerstattung; einziger zulässiger Folgebeleg einer Rechnung.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 43-44; `InvoiceSpecificLogic.CanBeForwardedInto()`.
---
## H
**Helpdesk / Ticket** (`HelpdeskClass = 10`)
Serviceanfrage mit Status, Kategorie, Priorität, verantwortlicher Person, Bearbeitern, Historie,
Checklisten und erfassten Zeiten.
*Beleg:* `src/backend/Centron.BL/Sales/Support/`; `CentronRights.md`, Abschnitt "Helpdesk".
**HelpdeskTimer** (`HelpdeskTimerClass = 4000056`)
Erfasste Arbeitszeit an einem Ticket, gekennzeichnet als berechenbar oder nicht berechenbar
(`Calculable`). Kann genau einer Rechnungsposition zugeordnet werden (`InvoiceAssetItemI3D`); ist sie
einem Beleg zugeordnet (`IsAssignedToAsset`), ist sie gegen Löschung geschützt.
*Beleg:* `HelpdeskTimerBL.DeleteHelpdeskTimer()`; `InvoiceSpecificLogic.SetTimerToPositionReference()`.
---
## I
**I3D** ("ID 3develop")
Namenskonvention für den Primärschlüssel jeder Tabelle (`int IDENTITY(1,1) NOT NULL`, gruppierter
Primärschlüsselindex). Fremdschlüssel tragen das Muster `{Zieltabelle}I3D`.
*Beleg:* `docs/guides/database/database-conventions.md`, Abschnitte 1.2/1.3;
`src/backend/Centron.Entities/PersistedEntity.cs`.
**ILogic / BLLogic / WSLogic**
Namenskonvention des Client-Datenzugriffs: `I{Modul}Logic` ist die Schnittstelle, `BL{Modul}Logic` die
Implementierung mit direktem Datenbankzugriff, `WS{Modul}Logic` die Implementierung über den
Web-Service. Die Auflösung erfolgt über den `ClassContainer`.
*Beleg:* `docs/getting-started/general-structure.md`;
`src/centron/Centron.WPF.UI/Services/Container/ClassContainer.cs`.
---
## L
**Lieferschein** (`DeliveryListClass = 3`, Tabellen `LiefKopf`/`LiefPos`, View `DeliveryLists`)
Kundenbeleg über die Auslieferung von Waren; häufigste Quelle einer Rechnung.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 27-28.
**Lizenz**
Eine GUID, die entweder eine anmeldefähige Anwendung oder ein Einzelfunktionsmerkmal repräsentiert.
Optional mit Anzahl (`count`), Gültigkeit bis Datum und Gültigkeit bis Version versehen. Die
verbindliche Quelle ist der Lizenzserver; `LicenseGuids.cs` hält eine synchronisierte Kopie.
*Beleg:* `docs/reference/security/licensing-system.md`;
`src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs`.
**LicenseUsageKind**
Zählweise der Lizenzbelegung: `PerUserAndPerMachine` (Standard) oder `PerUser` (u. a. Service-Board).
*Beleg:* `ApplicationKind.cs` Z. 173-177.
---
## M
**Mahnstufe** (`DunningLevel`)
Eskalationsstufe einer überfälligen Rechnung: `None`, `Level1`, `Level2`, `Level3`. Je Stufe werden
Datum und auslösender Benutzer festgehalten.
*Beleg:* `src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs` Z. 253-268.
**Mahnlauf** (`DunningRun`)
Nummerierter Vorgang, der die Mahnstufe der ausgewählten Rechnungen um jeweils eine Stufe erhöht und die
Mahndokumente erzeugt. Über die Laufnummer vollständig zurücknehmbar.
*Beleg:* `DunningRunBL.ExecuteDunningRun()` / `ResetDunningRun()`.
**Mahnstopp**
Zeitlich begrenzte Aussetzung des Mahnverfahrens für ein Objekt, mit Freitextbegründung.
*Beleg:* `DunningBL.UpdateDunningStopAndInfo()` Z. 392.
**Mandant** (`Mandator`, `Company = 53`)
Oberste organisatorische Einheit. Nummernkreise werden je Mandant, ergänzt um Filialvarianten, geführt.
*Beleg:* `NumberGroupBL.RefreshAllNumberGroups()` Z. 136-152.
---
## N
**Nummernkreis** (`NumberGroup`)
Konfiguration zur Vergabe fortlaufender Belegnummern, definiert über Mandant, Filiale, Nummernart
(`NumberGroupEnum`), Bereich (`RangeFrom`/`RangeTo`), Schrittweite (`Interval`) und aktuellen Stand
(`Current`).
*Beleg:* `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs`.
---
## O
**OpenTrans 2.1**
Branchenstandard für den elektronischen Belegaustausch, im System als `EdiDataType.OpenTrans21` (Wert 1)
unterstützt.
*Beleg:* `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs` Z. 17-18.
---
## R
**Rechnung** (`InvoiceClass = 4`, Tabellen `RechKopf`/`RechPos`, View `Invoices`)
Kundenbeleg zur Zahlungsanforderung. Sonderformen: **Barrechnung** (`IsCashAsset`, eigener Nummernkreis
`CashInvoice`, keine Weiterführung möglich) und **interne Rechnung** (`InternalInvoice`, bei reinen
Dienstleistungspositionen mit Nettosumme 0).
*Beleg:* `CentronObjectKindNumeric.cs` Z. 29-30; `InvoiceSpecificLogic.GetNumberGroup()` Z. 104-141.
**Result / Result<T>**
Einheitliches Ergebnisobjekt aller Geschäftslogikmethoden mit `Status` (`Success`, `Warning`, `Error`),
`Message` und maschinenlesbarem `MessageCode`.
*Beleg:* `src/backend/Centron.Interfaces/Results/`.
---
## S
**Sichbenu / Sichgrup / Sichtrus / Sichmemb**
Die vier historischen Tabellen des Mitarbeiter-Rechtemodells: Benutzer, Gruppen, Gruppe-Recht-Zuordnung,
Benutzer-Gruppe-Zuordnung.
*Beleg:* `AppRightsBL.CheckRightsFromUser()` Z. 97-101; `ResetDefaultRightGroups()` Z. 587-588.
**Skriptmethode** (`ScriptMethod{Nummer}`)
Versionierte, einmalig ausgeführte Codeeinheit zur Datenbankmigration, abgelegt als C#-Klasse mit
Skriptnummer und zugeordneter Anwendungsversion. 799 Dateien mit Nummern bis 11820.
*Beleg:* `src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/`.
**SpecificLogic** (`IReceiptSpecificLogic`)
Belegartspezifische Strategieimplementierung, an die die generische Belegverarbeitung (`ReceiptBL`) alle
typabhängigen Entscheidungen delegiert. 13 Implementierungen.
*Beleg:* `src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs`, `SpecificLogics.cs`.
**Stammdat / ApplicationSettings**
Die beiden Tabellen für Anwendungseinstellungen: `Stammdat` (historisch, adressiert über
`AppSettingsConst`) und `ApplicationSettings` (aktuell, adressiert über `ApplicationSettingID`).
*Beleg:* `docs/guides/development/settings-management.md`;
`src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs`.
---
## T
**Ticket (Sitzung)**
Nicht zu verwechseln mit dem Helpdesk-Ticket. Sitzungsmerkmal, das nach erfolgreicher Anmeldung und
bestandener Lizenzprüfung ausgegeben wird und alle weiteren Web-Service-Aufrufe autorisiert. Gebunden an
Benutzer, Anwendungsart, Lizenz-GUID, Gerät und Ablaufzeitpunkt.
*Beleg:* `src/backend/Centron.BL/Administration/Logins/TicketBL.cs`.
---
## V
**Vertrag** (`ContractClass = 22`, Tabellen `VertragKopf`/`VertragPos`, View `Contracts`)
Kundenbeleg für wiederkehrende Leistungen. Trägt Abrechnungsintervall (`BillingIntervalKind` ×
`BillingIntervalDuration`), Berechnungsart (`ContractCalculationKind`), Kontingentkonfiguration,
automatische Abrechnung (`AutomatedBilling`) und automatische Verlängerung
(`AutomatedProlongation`).
*Beleg:* `CentronObjectKindNumeric.cs` Z. 55-56;
`src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs`.
**Abrechnungsintervall** (`BillingIntervalKinds`)
Rhythmus der Vertragsabrechnung: `Daily` = 0 ("Tag(e)"), `Monthly` = 1 ("Monat(e)"), `Yearly` = 2
("Jahr(e)"), `Quarterly` = 3 ("Quartal(e)"), jeweils multipliziert mit `BillingIntervalDuration`.
*Beleg:* `src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs`.
---
## W
**Wareneingang** (`SupplierDeliveryList = 8`)
Lieferantenbeleg über den Eingang bestellter Waren.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 142-143.
**WE-Kalkulation** (`SupplierInvoice = 18`)
Lieferantenbeleg zur Bewertung des Wareneingangs (Eingangsrechnungsprüfung/Kalkulation). Einzige
Belegart, für die beim Speichern eine Abschlussrückfrage gestellt wird.
*Beleg:* `CentronObjectKindNumeric.cs` Z. 144-145; `ReceiptBL.CheckCloseReceipt()` Z. 4130-4150.
**WebAccount** (`Webaccount = 131`)
Kundenkonto für den Zugang zum Self-Service-Portal. Verfügt über ein eigenes Rechtemodell
(`WebAccountsRights`) und hat keinen Zugriff auf die interne Belegverwaltung.
*Beleg:* `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs`;
`ReceiptBL.CanUserViewReceipt()` Z. 10299-10302.
**WebCart**
Shop-Bereich des Nexus-Portals für Endkunden des Betreibers. Der Artikelkatalog stammt aus den
kundenspezifischen Sonderpreisen.
*Beleg:* `README.md`, Abschnitt "Contributing / 1. WebCart"; `src/nexus/CentronNexus/WebCart`.
**WebOffer / WebReceiptState**
Portalfunktion zur Angebotsansicht durch den Kunden mit den Rückmeldungen
`AcceptFullWebReceipt` (vollständige Annahme), `AcceptWebReceiptWithChangeRequests` (Annahme mit
Änderungswünschen), `Rejected` (Ablehnung), `WebOfferSign` (mit Unterschrift) und
`WebOfferSignedWithoutSignature` (ohne Unterschrift).
*Beleg:* `ReceiptBL.cs` Z. 5924-5928, 6302, 6360; `src/nexus/CentronNexus/WebOffer`.
---
## Z
**ZUGFeRD / XRechnung**
Standards für die elektronische Rechnung. ZUGFeRD bettet ein strukturiertes XML in das Rechnungs-PDF ein;
`IsZugferdXRechnungActive` schaltet auf die XRechnung-2.1-Variante des XML um.
*Beleg:* `src/backend/Centron.BL/EDI/Zugferd/`;
`src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs` Z. 108-111.
---
## Abkürzungen der Belegklassifikation (Methodik)
| Kennzeichen | Bedeutung |
|---|---|
| `PRIMÄR` | Im Code oder als Datenbank-Constraint durchgesetzte Regel |
| `SEKUNDÄR` | UI-Beschriftung, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter |
| `KONTEXT` | Kommentar, Commit-Nachricht, Ticketreferenz, Entwicklerdokumentation |
@@ -0,0 +1,325 @@
# Hypothesen und offene Fragen
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
---
## Vorbemerkung zur Systematik
Der Prompt verlangt, nicht eindeutig aus Artefakten ableitbare Aussagen als `[HYPOTHESE]` zu kennzeichnen.
In diesem Lauf wurde stattdessen der umgekehrte Weg gewählt: **In die Spezifikationsdokumente wurden
ausschließlich Anforderungen aufgenommen, die mindestens einen `PRIMÄR`-Beleg tragen.** Alle 71
Anforderungen (15 StRS, 32 SyRS, 24 SwRS) tragen daher den Status `belegt` bzw. `belegt; Workaround`;
keine trägt den Status `HYPOTHESE`.
Aussagen, die sich **nicht** hinreichend belegen ließen, wurden nicht zu Anforderungen formuliert, sondern
in diesem Dokument als offene Fragen gesammelt. Damit bleibt die Spezifikation frei von unbelegten
Soll-Aussagen; der Klärungsbedarf ist gleichwohl vollständig dokumentiert.
Jede Hypothese nennt: die vermutete Aussage, die vorhandenen (unzureichenden) Belege, die **fehlende
Information** und die daraus abzuleitende **offene Frage an den Fachexperten**.
---
## H-01 - Vollständigkeit des Belegstatusmodells
**[HYPOTHESE]** Das Statusmodell `ReceiptState` (offen/abgeschlossen/storniert) ist für **alle** Belegarten
identisch und kennt keine weiteren, fachlich relevanten Zwischenzustände.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` definiert genau drei Werte,
und `ReceiptBase.State` ist vom Typ `ReceiptState` - das gilt für alle Belegarten.
- `SEKUNDÄR`: In `ReceiptBL` finden sich zusätzliche, statusähnliche Konzepte, die nicht in `ReceiptState`
abgebildet sind: `WebReceiptState` (Z. 5924-5928, 6302, 6360), `FreigabeStatus` als Spalte in
`RechKopf` (`RechKopfMaps.cs`), `ReceiptCartReleaseSystemBL` (Freigabesystem für Belegkörbe),
`ReceiptUserState` (`src/backend/Centron.Entities/Entities/Sales/Receipts/UserState/`) und
`ReceiptCompleteReason`.
- `KONTEXT`: `docs/reference/receipts/receipts-backend-architecture.md` nennt abweichend vier Zustände
("Draft, Released, Processed, Cancelled"), die im Code so nicht existieren.
**Fehlende Information**
Es ist unklar, ob `FreigabeStatus`, `ReceiptUserState` und `WebReceiptState` eigenständige fachliche
Statusmaschinen darstellen, die parallel zu `ReceiptState` laufen, oder ob es sich um Attribute ohne
Zustandslogik handelt. Die Dokumentation widerspricht dem Code.
**Offene Frage**
Wie viele fachlich unterscheidbare Belegzustände gibt es tatsächlich, und in welcher Beziehung stehen
`ReceiptState`, `FreigabeStatus`, `ReceiptUserState` und `WebReceiptState` zueinander?
**Betroffene Anforderung:** SyRS-002
---
## H-02 - Behandlung des Tagesintervalls in der Vertragsabrechnung
**[HYPOTHESE]** Die Gleichbehandlung von `BillingIntervalKinds.Daily` und `.Monthly` in
`AutomaticFacturaBL.Contracts.StoreBookedContingent()` ist ein Fehler und kein beabsichtigtes Verhalten.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs`
Z. 1105-1108: `case BillingIntervalKinds.Daily: case BillingIntervalKinds.Monthly:
invoiceMonthBillingInterval = billingParam.BillingIntervalDuration; break;`
- `PRIMÄR`: `ReportObjectsBL.cs` Z. 272-274 und `ReceiptToReportObjectMap.cs` Z. 354-356 behandeln
`Daily` überhaupt nicht und fallen auf die Vorbelegung `nMonth = 1` zurück.
- `PRIMÄR`: `AutomaticFacturaBL.Contracts.cs` Z. 1060 (`if (billingParam.BillingIntervalKind ==
BillingIntervalKinds.Daily)`) zeigt, dass `Daily` an anderer Stelle sehr wohl gesondert behandelt wird.
**Fehlende Information**
Es fehlt eine Aussage darüber, ob Verträge mit Tagesintervall im Produktivbetrieb tatsächlich vorkommen.
Ohne Datenbestand lässt sich nicht entscheiden, ob es sich um toten Code oder um einen wirksamen
Berechnungsfehler handelt.
**Offene Frage**
Werden Verträge mit `BillingIntervalKind = Daily` produktiv genutzt? Falls ja: Welcher
Abrechnungszeitraum ist fachlich korrekt?
**Betroffene Anforderungen:** SyRS-019, SwRS-022
---
## H-03 - Wirksamkeit der Belegabschluss-Prüfung im Helpdesk
**[HYPOTHESE]** Der Abschluss eines Helpdesk-Tickets über `HelpdeskCloseBL.CloseHelpdesk()` umgeht die
Checklistenprüfung, weil `HelpdeskCloseBL.CanCloseHelpdesk()` unbedingt `true` zurückgibt.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs` Z. 129 ruft `CanCloseHelpdesk`,
Z. 158-165 gibt diese `return true;` mit dem Kommentar `//Todo: if rma exists check if finished` zurück.
- `PRIMÄR`: `UpdateHelpdeskBL.CanHelpdeskClose()` (Z. 492-518) und
`HelpdeskWebServiceBL.CanHelpdeskClose()` (Z. 283-309) enthalten die tatsächliche Prüfung.
**Fehlende Information**
Es ließ sich nicht abschließend ermitteln, ob alle Aufrufwege zum Ticketabschluss (Rich Client, Nexus,
Web-Service, automatische Prozesse) vorher `UpdateHelpdeskBL.CanHelpdeskClose` bzw.
`HelpdeskWebServiceBL.CanHelpdeskClose` aufrufen, oder ob mindestens ein Weg direkt auf
`HelpdeskCloseBL.CloseHelpdesk` geht. Eine vollständige Aufrufanalyse über alle Clients war im Rahmen
dieses Laufs nicht möglich.
**Offene Frage**
Existiert ein produktiv erreichbarer Weg, ein Ticket mit offenen Pflicht-Checklistenpunkten
abzuschließen?
**Betroffene Anforderung:** SyRS-017
---
## H-04 - Funktionsfähigkeit der DSGVO-Datenbereinigung
**[HYPOTHESE]** Die Funktion "Datenbank bereinigen" führt derzeit keine Löschung durch.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs` Z. 63-68:
`DataSecurityExecuteCleanUp` prüft Recht und Feature und gibt danach unmittelbar
`Result.AsSuccess()` zurück; der Parameter `selectedStats` wird nicht ausgewertet.
- `SEKUNDÄR`: Das Recht 20800024 "Datenbank bereinigen" existiert (`AppRightsBL.
GetAssignableAdminRightI3Ds()` Z. 757) und ein UI-Modul `Modules.Administration.DSGVO` ist registriert.
- `SEKUNDÄR`: `DsgvoDeleteRightDeleteContacts` (Z. 787) ist demgegenüber ausimplementiert.
**Fehlende Information**
Unklar bleibt, ob die Löschung an anderer Stelle (z. B. clientseitig oder über einen Hintergrunddienst)
ausgeführt wird oder ob die Methode ein unvollständiger Stand ist. Eine Ausführung des Systems war nicht
Teil des Auftrags.
**Offene Frage**
Ist die Datenbankbereinigung ein produktiv genutztes Feature? Falls ja: Wo findet die eigentliche
Löschung statt?
**Betroffene Anforderungen:** StRS-012, SyRS-025
---
## H-05 - Invalidierung des Rechte-Zwischenspeichers
**[HYPOTHESE]** Eine Rechteänderung wirkt für einen bereits angemeldeten Benutzer erst nach einer neuen
Datenbanksitzung, weil der Rechte-Cache nicht invalidiert wird.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 646:
`Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", () =>
GetAllAppRightsFromUser(appUserI3D))` - kein Invalidierungsaufruf in den ändernden Methoden
(`AddRightToRightGroup`, `RemoveRightFromRightGroup`, `AddUserToRightGroup`, …).
- `PRIMÄR`: `src/backend/Centron.DAO/SessionCache.cs` bindet den Cache an die `DAOSession`.
**Fehlende Information**
Die Lebensdauer einer `DAOSession` im Web-Service-Betrieb ließ sich nicht abschließend bestimmen. Ist sie
je Aufruf neu (`using (BLSession session = new BLSession())` im `AuthenticateInterceptor` deutet darauf
hin), ist die Auswirkung vernachlässigbar; ist sie langlebig, entsteht ein Sicherheitsrisiko bei
Rechteentzug.
**Offene Frage**
Wie lange lebt eine `DAOSession` im Web-Service? Wird ein Rechteentzug für einen aktiven Benutzer sofort
wirksam?
**Betroffene Anforderungen:** SyRS-006, SwRS-017
---
## H-06 - Vorrangregel bei der ZUGFeRD-Aktivierung
**[HYPOTHESE]** Die belegbezogene ZUGFeRD-Einstellung (`GetLocalZUGFeRDSetting(receipt)`) kann die globale
Einstellung nur aktivieren, nicht deaktivieren.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 3273: die Bedingung lautet
`(new InvoiceZugferdBL(Session).IsZugferdEnabled() || this.GetLocalZUGFeRDSetting(receipt) == true)` -
eine ODER-Verknüpfung, die keine Deaktivierung durch die belegbezogene Einstellung erlaubt.
**Fehlende Information**
Es fehlt eine fachliche Aussage darüber, ob ein einzelner Beleg bewusst **ohne** ZUGFeRD-XML erzeugt
werden können soll, obwohl die Funktion global aktiviert ist (z. B. bei Auslandskunden).
**Offene Frage**
Soll die belegbezogene Einstellung die globale auch abschalten können?
**Betroffene Anforderung:** SyRS-024
---
## H-07 - Verbindlichkeit der Dokumentation als Anforderungsquelle
**[HYPOTHESE]** Die Inhalte unter `docs/` beschreiben den Ist-Zustand zuverlässig genug, um als
ergänzende Anforderungsquelle zu dienen.
**Vorhandene Belege**
- `SEKUNDÄR`: 50 Markdown-Dokumente mit teilweise sehr hoher Detailtiefe (u. a. 28 005 Bytes
ZUGFeRD-Feldzuordnung, 18 771 Bytes Belegarchitektur) und konkreten Datei- und Zeilenverweisen, die
sich in Stichproben als zutreffend erwiesen (z. B. Belegart-/Tabellenzuordnung, `AnlageArt`-Werte).
- `KONTEXT`: **Gegenbeleg** - `docs/reference/receipts/receipts-backend-architecture.md`, Abschnitt
"Receipt State Management", nennt vier Zustände (Draft, Released, Processed, Cancelled), die im Code
nicht existieren (siehe H-01).
- `KONTEXT`: **Gegenbeleg** - `docs/getting-started/general-structure.md` weist selbst darauf hin, dass
die beschriebene Struktur vielfach nicht eingehalten ist.
- `KONTEXT`: `docs/getting-started/documentation-rules.md` und
`docs/getting-started/ai-codebase-navigation.md` deuten darauf hin, dass Teile der Dokumentation
werkzeuggestützt erzeugt wurden.
**Fehlende Information**
Es ist unbekannt, welche Dokumente redaktionell geprüft wurden und welche generiert sind. Da mindestens
ein Dokument nachweislich vom Code abweicht, ist die Verlässlichkeit uneinheitlich.
**Offene Frage**
Welche Dokumente unter `docs/` sind fachlich abgenommen und dürfen als Anforderungsquelle gelten?
**Konsequenz für diese Spezifikation:** Dokumentationsinhalte wurden durchgängig nur als `KONTEXT`
klassifiziert und nie als alleiniger Beleg einer Anforderung verwendet.
---
## H-08 - Umfang des Delphi-Altsystems im Zielsystem
**[HYPOTHESE]** Ein Teil des Fachverhaltens wird weiterhin von einem Delphi-Altsystem (c-entron Delphi,
Versionsschema 9.3.x) erbracht, das dieselbe Datenbank und dieselben Lizenzen nutzt.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs`,
`TryFixCentronDelphiVersionNumber()` (Z. 304-330) mit dem Kommentar "The c-entron Delphi uses the same
license-guid as the c-entron.NET, but has a version-number like 9.3.X.Y" und dem daraus folgenden
Verzicht auf die Versionsprüfung für Delphi-Clients.
- `PRIMÄR`: `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 14: "Neue Konstanten für .Net
werden autark von c-entron Delphi angelegt Sie beginnen ab dem Wert 7600000".
- `SEKUNDÄR`: Die durchgängig deutschen Alttabellennamen (`RechKopf`, `AngPos`, `Sichbenu`, `Sichgrup`,
`Sichtrus`, `Sichmemb`, `Stammdat`, `Kunden`, `Kreditor`, `Taetigkeiten`) legen einen gemeinsamen
Ursprung nahe.
**Fehlende Information**
Der Delphi-Quellcode liegt nicht im Arbeitsverzeichnis. Es lässt sich daher nicht bestimmen, welche
Fachfunktionen ausschließlich dort implementiert sind und in dieser Spezifikation folglich fehlen.
**Offene Frage**
Welche Fachfunktionen werden heute ausschließlich vom Delphi-System erbracht, und sind sie Teil des
Migrationsumfangs?
**Konsequenz:** Diese Spezifikation beschreibt ausschließlich das .NET-System. Ein möglicher blinder Fleck
ist im `Analysebericht.md` als Lücke L-01 vermerkt.
---
## H-09 - Verbindlichkeit der Datenbankkonventionen für den Altbestand
**[HYPOTHESE]** Die in `docs/guides/database/database-conventions.md` geforderten Nachverfolgungs- und
Soft-Delete-Spalten sind nur in neueren Tabellen tatsächlich vorhanden.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.DAO/Mappings/TemporaryEntities/RechKopfMaps.cs` bildet die Alttabelle
`RechKopf` ab und verwendet abweichende Spaltennamen (`ErstelltDurch`, `GeaendertVonI3D`, `ErstellerI3D`,
`KundenID`, `AnschriftID`) statt der konventionsgemäßen `CreatedByI3D`/`ChangedByI3D`.
- `PRIMÄR`: `docs/guides/database/database-conventions.md`, Abschnitt 4: "Historical tables and columns may
use German names … Do not rename existing German table/column names".
**Fehlende Information**
Ohne Datenbankzugriff (es liegen keine `.sql`-Dateien im Repository, das Schema entsteht ausschließlich
zur Laufzeit über die 799 Skriptmethoden) lässt sich der tatsächliche Anteil konventionskonformer Tabellen
nicht bestimmen.
**Offene Frage**
Wie hoch ist der Anteil der Tabellen ohne vollständige Audit- und Soft-Delete-Spalten, und ist eine
Vereinheitlichung im Zielsystem vorgesehen?
**Betroffene Anforderungen:** SwRS-006, SwRS-007
---
## H-10 - Kennwortmigration bei der Neuimplementierung
**[HYPOTHESE]** Bestehende Kennwörter können bei einer Migration nicht in ein modernes Hashverfahren
überführt werden, ohne dass die Benutzer sich mindestens einmal anmelden oder ihr Kennwort zurücksetzen.
**Vorhandene Belege**
- `PRIMÄR`: `src/backend/Centron.Common/TextCoding/SHA1Decoder.cs` erzeugt einen nicht umkehrbaren Hash;
Klartextkennwörter liegen nicht vor.
- `PRIMÄR`: `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs` Z. 48:
`// TODO the password should be salted!!!`
**Fehlende Information**
Es ist nicht bekannt, ob im Zielsystem ein Übergangsbetrieb vorgesehen ist, in dem beide Verfahren
parallel geprüft werden, oder ob ein organisatorischer Kennwort-Reset akzeptabel ist.
**Offene Frage**
Wie soll die Kennwortmigration erfolgen - schrittweises Neuhashen bei der nächsten Anmeldung oder
vollständiger Reset?
**Betroffene Anforderung:** SwRS-009
---
## H-11 - Fachliche Bedeutung der 750 Rechtekonstanten
**[HYPOTHESE]** Ein relevanter Teil der 750 definierten Rechte ist nicht mehr in Verwendung.
**Vorhandene Belege**
- `PRIMÄR`: `UserRightsConst.cs` enthält 750 aktive und mehrere auskommentierte Konstanten, teils mit
Hinweisen wie `//public const int //RECHTDESMENUITEMSWIRDIMPROGRAMMAUCHGEBRAUCHTRIGHT_WARTUNG=10480;`
und `//public const int //WARTUNGC-WIMRIGHT_VERTRAGSARTEN=10492;`.
- `SEKUNDÄR`: `CentronRights.md` dokumentiert für das Recht `RIGHT_KALENDERANZEIGENALLE` ausdrücklich:
"Currently, this right is not used."
- `SEKUNDÄR`: `AppRightsBL.ResetDefaultRightGroups()` stellt eine Standardstruktur her, die nicht
notwendigerweise alle 750 Rechte abdeckt.
**Fehlende Information**
Eine belastbare Verwendungsanalyse aller 750 Rechtekonstanten über die gesamte Codebasis (16 063
`.cs`-Dateien plus 1233 XAML- und 491 Razor-Dateien) wurde in diesem Lauf nicht durchgeführt.
**Offene Frage**
Welche Rechte sind produktiv relevant und in das Zielsystem zu übernehmen?
**Betroffene Anforderung:** StRS-003
---
## 12. Zusammenfassung
| Nr. | Thema | Risikoschwerpunkt | Priorität für die Validierung |
|---|---|---|---|
| H-01 | Vollständigkeit des Belegstatusmodells | Fakturierung | hoch |
| H-02 | Tagesintervall in der Vertragsabrechnung | Fakturierung | hoch |
| H-03 | Umgehbare Ticketabschluss-Prüfung | Prozessintegrität | hoch |
| H-04 | Wirkungslose DSGVO-Bereinigung | Recht/Datenschutz | hoch |
| H-05 | Invalidierung des Rechte-Caches | Sicherheit | hoch |
| H-06 | Vorrangregel ZUGFeRD | E-Rechnung | mittel |
| H-07 | Verlässlichkeit der Dokumentation | Methodik | mittel |
| H-08 | Umfang des Delphi-Altsystems | Migrationsumfang | hoch |
| H-09 | Konventionskonformität des Altschemas | Datenmigration | mittel |
| H-10 | Kennwortmigration | Sicherheit/Migration | hoch |
| H-11 | Nutzungsgrad der 750 Rechte | Migrationsumfang | mittel |
@@ -0,0 +1,661 @@
# StRS - Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE c-entron ERP)
**Erstellt durch:** Reverse Requirements Engineering (statische Artefaktanalyse)
**Norm:** ISO/IEC/IEEE 29148:2018, Abschnitt 9.3 (Stakeholder Requirements Specification)
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha` (`version.json`)
**Datum:** 2026-08-25
---
## 1. Zweck und Geltungsbereich
Dieses Dokument beschreibt die aus der Codebasis rekonstruierten Anforderungen aus Sicht der Stakeholder (Fachbereiche, Endanwender, Betreiber, Kunden des Betreibers). Es bildet die oberste Ebene der dreistufigen Spezifikation (StRS → SyRS → SwRS).
Alle Aussagen sind aus lesbaren Artefakten des Arbeitsverzeichnisses abgeleitet. Jede Anforderung trennt die belegte technische Beobachtung (`Fakt`) von der fachlichen Interpretation (`Aussage`).
## 2. Systemüberblick
c-entron ist eine ERP-Suite für den deutschen Markt mit Schwerpunkt IT-Systemhaus/IT-Dienstleistung. Sie besteht aus:
| Teilsystem | Technologie | Pfad |
|---|---|---|
| c-entron.NET (Rich Client) | WPF/XAML, DevExpress | `src/centron/Centron.WPF.UI` |
| Web-Service (Backend-API) | ASP.NET Core, WCF-Bridge, NHibernate | `src/webservice/`, `src/backend/` |
| c-entron Nexus (c-entron Web) | Blazor, DevExpress Blazor | `src/nexus/CentronNexus` |
| Outlook Add-In | Office Add-In | `src/nexus/CentronNexus.OutlookAddIn` |
| Fremdsystem-Konnektoren | .NET Bibliotheken | `src/apis/`, `src/backend/Centron.Gateway` |
## 3. Stakeholder (aus Artefakten abgeleitet)
| Stakeholder | Beleg für Existenz der Rolle |
|---|---|
| Mitarbeiter/Sachbearbeiter (`AppUser`, `Employee`) | `src/backend/Centron.Entities/Entities/Administration/…` (`AppUser`), Tabelle `Sichbenu` |
| Rechteadministrator | `UserRightsConst.Administration.UserRightsManagement`, `AppRightsBL.SaveRightGroup` |
| Kunde des Betreibers (Web-Account) | `WebAccount`, `WebAccountAuthenticator`, `src/nexus/CentronNexus/WebCart` |
| Buchhaltung/Forderungsmanagement | `DunningBL`, `DunningRunBL`, `UserRightsConst.Controlling.Finances` |
| Servicetechniker/Helpdesk-Bearbeiter | `HelpdeskTimerBL`, `CentronRights.md` Abschnitt Helpdesk |
| Betreiber/IT-Administrator | `docker/`, `deployment/WixSharpInstaller`, `nlog.config` |
| Lieferant (via EDI) | `src/backend/Centron.BL/EDI/`, `SupplierEdiConfigurations` |
| Lizenzgeber (NEXOWARE Systems GmbH) | `Directory.Build.props` (`<Company>`), `LicenseManager`, Lizenzserver-Anbindung |
---
## 4. Stakeholder-Anforderungen
---
```
ID: StRS-001
Titel: Durchgängige Belegkette im Vertriebsprozess
Ebene: StRS
Typ: funktional
Akteur: Sachbearbeiter Vertrieb
Vorbedingung: Angemeldeter Benutzer mit Belegrechten; Kunde im Stammsatz vorhanden
Fakt: Das Enum `CentronObjectKindNumeric` definiert die Kundenbelegarten Angebot (1), Auftrag (2),
Lieferschein (3), Rechnung (4), Abholschein (5), Gutschrift (6), Vertrag (22) und stellt die
Prüfmethode `IsCustomerReceipt()` bereit, die genau diese sieben Arten als Kundenbeleg wertet.
`InvoiceSpecificLogic.CanBeForwardedFrom()` gibt an, dass eine Rechnung aus Lieferschein,
Auftrag, Angebot und Vertrag entstehen kann, `CanBeForwardedInto()` erlaubt die Weiterführung
in eine Gutschrift.
Aussage: Das System soll den kaufmännischen Vertriebsprozess über die Belegarten Angebot, Auftrag,
Lieferschein, Abholschein, Rechnung, Gutschrift und Vertrag abbilden und die Weiterführung
eines Belegs in einen Folgebeleg unterstützen, wobei die zulässigen Übergänge je Belegart
definiert sind.
Ergebnis: Aus einem Vorgängerbeleg entsteht ein Folgebeleg mit übernommenen Positionen; die Herkunft
bleibt über die Beleghistorie nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Zeilen 23-30, 41-44, 55-56 sowie
Methode `CentronObjectKindNumericExtensions.IsCustomerReceipt()` (Z. 273-287) - Begründung: Die
Belegarten sind als typisierte Konstanten im Code festgelegt und werden zur Laufzeit zur
Klassifikation herangezogen; damit ist der Belegartenumfang durchgesetzt, nicht nur dokumentiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs,
`CanBeForwardedFrom()` / `CanBeForwardedInto()` (Z. 279-280) - Begründung: Die Methoden liefern
die erlaubten Quell-/Zielbelegarten und werden vom generischen `ReceiptBL` zur Steuerung der
Weiterführung ausgewertet; die Belegkette ist damit im Code erzwungen.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs,
`GetAssetName()` (Z. 303-317) mit den UI-Bezeichnungen "Angebot", "Auftrag", "Lieferschein",
"Abholschein", "Rechnung", "Gutschrift", "Vertrag" - Begründung: Belegt die fachlichen
Bezeichnungen, unter denen die Belegarten dem Anwender präsentiert werden.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md, Tabelle "Receipt Types Hierarchy" -
Begründung: Bestätigt die Zuordnung Belegart → Entität → Tabelle → View aus Entwicklersicht.
Prüfidee: Für jede der sieben Kundenbelegarten kann ein Beleg angelegt werden; eine Rechnung lässt sich
aus Lieferschein/Auftrag/Angebot/Vertrag erzeugen und in eine Gutschrift weiterführen; die
Weiterführung einer Rechnung in einen Auftrag wird abgelehnt.
Tracelinks: SyRS-001, SyRS-002, SyRS-003
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-002
Titel: Mandanten- und Filialorganisation
Ebene: StRS
Typ: funktional
Akteur: Betreiber mit mehreren Standorten
Vorbedingung: Mindestens ein Mandant (`Mandator`) angelegt
Fakt: `NumberGroupBL.RefreshAllNumberGroups()` ermittelt den Default-Mandanten und legt für jede
Filiale (`BranchBL.GetBaseBranchList`) eigene Nummernkreise an. `ReceiptBase` besitzt die
Felder `BranchI3D` und `BranchOrigin`. `AppRightsBL.GetAllRightGroups()` filtert Rechtegruppen
auf die Filiale des Benutzers, wenn dieser das Recht `MANAGE_RIGHTS_ONLY_OWN_BRANCH` besitzt.
`ApplicationKind`/`LicenseGuids` führen eine eigene Lizenz für die Filialfunktionalität.
Aussage: Das System soll den Betrieb mehrerer Mandanten und Filialen innerhalb einer Installation
unterstützen und Datenobjekte (Belege, Rechtegruppen, Nummernkreise) einer Filiale zuordnen
können.
Ergebnis: Belege, Nummernkreise und Rechtegruppen sind filialbezogen führbar; filialbezogene
Einschränkungen sind auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs,
`RefreshAllNumberGroups()` (Z. 136-152) - Begründung: Der Code legt je Filiale einen eigenen
Satz Nummernkreise an; die Filialstruktur ist damit strukturbildend, nicht nur ein Attribut.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Z. 19-20
(`BranchI3D`, `BranchOrigin`) - Begründung: Jeder Beleg trägt eine Filialzuordnung als
persistiertes Feld der Basisklasse aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `GetAllRightGroups()` (Z. 39-48)
und `SaveRightGroup()` (Z. 391-393) - Begründung: Filialgrenzen werden bei der
Rechteverwaltung serverseitig durchgesetzt.
- [KONTEXT] docs/reference/security/licensing-system.md, Abschnitt "Only Licenses" nennt die
"branch functionality" als separat lizenzierbares Einzelfeature - Begründung: Zeigt, dass die
Filialfunktion ein eigenständiges, kommerziell abgegrenztes Fachmerkmal ist.
Prüfidee: Nach Anlage einer zweiten Filiale existieren für diese eigene Nummernkreiseinträge; ein Beleg
dieser Filiale trägt deren `BranchI3D`.
Tracelinks: SyRS-004, SyRS-005
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-003
Titel: Rollenbasierte Zugriffssteuerung über Rechtegruppen
Ebene: StRS
Typ: Sicherheit
Akteur: Rechteadministrator
Vorbedingung: Benutzer (`AppUser`) und Rechtegruppen (`AppGroup`) existieren
Fakt: Die Datei `UserRightsConst.cs` definiert 750 als `public const int` deklarierte Rechte-IDs in
einer fachlich gegliederten Klassenhierarchie (z. B. `Sales.Customer.Helpdesk`,
`Administration.UserRightsManagement`, `Controlling.Finances`). Rechte werden nicht direkt an
Benutzer, sondern über die Tabellen `Sichtrus` (Gruppe→Recht) und `Sichmemb` (Benutzer→Gruppe)
vergeben; `AppRightsBL.CheckRightsFromUser()` verknüpft beide per SQL-Join.
Aussage: Das System soll Zugriffsrechte fein granular (mindestens auf Funktions- und Modulebene)
definieren und ausschließlich über Gruppenzugehörigkeit an Benutzer vergeben.
Ergebnis: Ein Benutzer erhält genau die Rechte der Gruppen, denen er angehört; die Rechtevergabe ist
zentral über Gruppen administrierbar.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs
(2819 Zeilen, 750 Rechtekonstanten) - Begründung: Die Rechte-IDs sind der im gesamten Code
verwendete Schlüssel für Berechtigungsprüfungen; ihre Existenz und Granularität ist damit
durchgesetzt.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `CheckRightsFromUser()`
(Z. 95-111) mit dem SQL `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON
sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D` - Begründung: Das Statement zeigt das
durchgesetzte Datenmodell Benutzer→Gruppe→Recht.
- [SEKUNDÄR] CentronRights.md (Repository-Wurzel) - Begründung: Beschreibt die fachliche Bedeutung
einzelner Rechte, insbesondere das Konzept "restricting right" (einschränkende Rechte).
- [KONTEXT] docs/guides/development/check-userrights.md - Begründung: Dokumentiert die verbindliche
Prüfmethodik für Entwickler.
Prüfidee: Ein Benutzer ohne Gruppenzugehörigkeit erhält aus `CheckRightsFromUser` eine leere Rechteliste;
nach Aufnahme in eine Gruppe mit Recht X enthält die Liste X.
Tracelinks: SyRS-006, SyRS-007, SyRS-008
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-004
Titel: Lizenzabhängiger Funktionsumfang
Ebene: StRS
Typ: funktional / Sicherheit
Akteur: Lizenzgeber, Betreiber
Vorbedingung: Lizenzdatei vom Lizenzserver bezogen oder aus Cache verfügbar
Fakt: `LicenseManager` prüft je Lizenz-GUID Vorhandensein (`HasLicense`), Anzahl (`GetLicenseCount`)
und Gültigkeit bis Version (`CheckLicenseVersion`). `ApplicationKind` definiert 44 anmeldefähige
Anwendungen, jeweils mit Lizenz-GUID, Ablaufart (`ExpirationKind`) und Nutzungsart
(`LicenseUsageKind`). `AccessTokenBL.ValidateToken()` bricht mit "Sie haben nicht die
notwendige Lizenz!" ab, wenn `LicenseGuids.AccessTokenModule` fehlt.
Aussage: Das System soll den nutzbaren Funktionsumfang je Installation über Lizenzen steuern, wobei
Lizenzen sowohl ganze Anwendungen als auch einzelne Funktionsmerkmale abdecken und optional
mengen- sowie versions- bzw. datumsbegrenzt sein können.
Ergebnis: Nicht lizenzierte Anwendungen können sich nicht anmelden; nicht lizenzierte Einzelfunktionen
sind nicht nutzbar oder werden nicht angezeigt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, `CheckLicense()`
(Z. 258-302) - Begründung: Setzt Lizenzprüfung inkl. Mengenbegrenzung als harte Fehlerbedingung
beim Anmeldevorgang durch.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs, Z. 11-53 -
Begründung: Enthält die abschließende Liste anmeldefähiger Anwendungen mit ihren
Lizenz-GUIDs; `ApplicationKind.GetKindByLicenseGuid()` wird beim Login zwingend ausgewertet.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs, `ValidateToken()`
(Z. 381-383) - Begründung: Beispiel für eine Einzelfunktion, deren Nutzung an eine Lizenz
gebunden ist und die ohne Lizenz einen Fehler zurückgibt.
- [KONTEXT] docs/reference/security/licensing-system.md - Begründung: Erläutert das Lizenzmodell
(GUID, count, valid until date, valid until version) aus Herstellersicht.
Prüfidee: Eine Anmeldung mit einer Anwendung, deren Lizenz-GUID nicht in der Lizenzdatei enthalten ist,
wird mit Lizenzfehler abgewiesen; ein Aufruf der Access-Token-Validierung ohne Modullizenz
liefert die Fehlermeldung "Sie haben nicht die notwendige Lizenz!".
Tracelinks: SyRS-014, SyRS-015
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-005
Titel: Serviceprozess über Helpdesk-Tickets
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Helpdesk-Bearbeiter
Vorbedingung: Benutzer besitzt das Recht `SHOW_HELPDESK`
Fakt: Es existiert ein eigenständiges Ticketsystem mit ca. 50 BL-Klassen unter
`src/backend/Centron.BL/Sales/Support/` (u. a. `HelpdeskBL`, `HelpdeskStatusBL`,
`HelpdeskCategoryBL`, `HelpdeskCloseBL`, `HelpdeskForwardBL`, `HelpdeskSchedulerBL`,
`HelpdeskTimerBL`). `CentronObjectKindNumeric.HelpdeskClass = 10` weist das Ticket als
eigenständige Objektart aus. `CentronRights.md` listet 18 Hauptrechte und mehrere
einschränkende Rechte allein für den Helpdesk.
Aussage: Das System soll Serviceanfragen als Tickets mit Status, Kategorie, Priorität, verantwortlicher
Person, Bearbeitern, Historie und Checklisten führen und deren Lebenszyklus bis zum Abschluss
steuern.
Ergebnis: Ein Ticket durchläuft definierte Status bis zum Abschlussstatus; alle Änderungen sind über die
Tickethistorie nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/ (Verzeichnis, ca. 50 BL-Klassen; u. a.
`HelpdeskCloseBL.cs`, `HelpdeskHistoryBL.cs`, `HelpdeskStatusBL.cs`) - Begründung: Umfang und
Struktur der implementierten Logik belegen den eigenständigen Fachprozess.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs, `CloseHelpdesk()` (Z. 120-155):
Setzt `helpdeskRequest.Data.HelpdeskState = closedState` und löscht zugehörige ToDos -
Begründung: Der Abschlussvorgang ist als durchgesetzter Zustandsübergang implementiert.
- [SEKUNDÄR] CentronRights.md, Abschnitt "Helpdesk" (18 nummerierte Rechte) - Begründung: Zeigt die
fachliche Feingliederung des Prozesses aus Anwendersicht.
- [KONTEXT] docs/features/automatic-helpdesk-creation-templates.md (29 852 Bytes) - Begründung: Beschreibt
die automatisierte Ticketerzeugung als ausgebautes Teilfeature.
Prüfidee: Ein Ticket kann angelegt, einem Bearbeiter zugewiesen, kategorisiert und abgeschlossen werden;
nach Abschluss trägt es den in den Einstellungen hinterlegten Abschlussstatus.
Tracelinks: SyRS-017
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-006
Titel: Leistungserfassung und Überführung in die Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker, Abrechnung
Vorbedingung: Ticket existiert; Benutzer besitzt das Recht `EDIT_TIME`
Fakt: `HelpdeskTimer` besitzt die Felder `Calculable` (berechenbar), `Start`, `Stop`, `Article`,
`InvoiceAssetItemI3D` und `IsAssignedToAsset`. `InvoiceSpecificLogic.SetTimerToPositionReference()`
wirft eine Exception mit dem Text "Die Zeit (I3D {…}) wurde bereits durch eine andere
Rechnungsposition (I3D {…}) abgerechnet.", wenn eine Zeit bereits einer anderen
Rechnungsposition zugeordnet ist. `HelpdeskTimerBL.DeleteHelpdeskTimer()` verweigert das Löschen
mit "Die Helpdesk Zeit wurde einem Beleg zugewiesen. Löschen ist nicht möglich.".
Aussage: Das System soll erfasste Arbeitszeiten mit Kennzeichnung ihrer Berechenbarkeit führen, sie
genau einer Abrechnungsposition zuordnen können und bereits abgerechnete Zeiten gegen Löschung
und Mehrfachabrechnung schützen.
Ergebnis: Eine erfasste Zeit ist höchstens einer Rechnungsposition zugeordnet; abgerechnete Zeiten sind
unveränderlich gegenüber Löschung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs,
`SetTimerToPositionReference()` (Z. 615-623) - Begründung: Verhindert per Exception die
Doppelabrechnung derselben Zeit; das ist eine durchgesetzte Abrechnungsregel.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs, `DeleteHelpdeskTimer()` (Z. 553-565) -
Begründung: Rechteprüfung (`DELETE_HELPDESK_TIMER`) und Sperre bei Belegzuordnung sind
serverseitig implementiert.
- [SEKUNDÄR] CentronRights.md, Abschnitte 8 und 9 ("Helpdeskzeiten verschieben"/"löschen": "But only if the
ticket is not part of a receipt.") - Begründung: Bestätigt die Regel aus Anwendersicht.
- [KONTEXT] Commit `0afd60a422` "Fix timer type (Calculable) (#98)" - Begründung: Belegt, dass die
Berechenbarkeitskennzeichnung aktiv gepflegtes Fachverhalten ist.
Prüfidee: Eine Zeit, die einer Rechnungsposition zugeordnet ist, kann nicht gelöscht werden; der Versuch,
sie einer zweiten Rechnungsposition zuzuordnen, führt zu einem Fehler.
Tracelinks: SyRS-018
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-007
Titel: Vertrags- und Abonnementgeschäft mit wiederkehrender Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Vertragsverwaltung, Abrechnung
Vorbedingung: Vertrag (Belegart `ContractClass`) mit Abrechnungsintervall angelegt
Fakt: Der Vertrag ist eine eigene Belegart (`CentronObjectKindNumeric.ContractClass = 22`,
Beschreibung "Vertrag"). `BillingIntervalKinds` definiert die Intervalle Tag(e)=0, Monat(e)=1,
Jahr(e)=2, Quartal(e)=3. `AutomaticFacturaBL.Contracts` (Teil eines ca. 6100-Zeilen-Komplexes)
berechnet Abrechnungszeiträume, Kontingentverbräuche und erzeugt Rechnungen aus Verträgen.
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall (Tag, Monat, Quartal, Jahr
jeweils mit Faktor) führen und daraus wiederkehrend Rechnungen erzeugen können, einschließlich
Verbrauchs- und Kontingentabrechnung.
Ergebnis: Zum jeweiligen Abrechnungstermin entstehen Rechnungen mit dem vertraglich vereinbarten Umfang;
Kontingentverbräuche werden fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs,
Z. 8-22 - Begründung: Legt die zulässigen Abrechnungsintervalle typisiert fest.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs,
`StoreBookedContingent()` (Z. 1098-1120) und `isFirstIntervalDay()` (Z. 1355-1373) -
Begründung: Zeigt die durchgesetzte Umrechnung von Intervallart in Abrechnungsmonate und die
Prüfung auf Intervallbeginn.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Z. 55-58: `[Description("Vertrag")]
ContractClass = 22` und `[Description("Vertragsart")] ContractKindClass = 86` - Begründung:
Belegt Vertrag und Vertragsart als eigenständige Fachobjekte.
- [KONTEXT] docs/reference/receipts/contracts-backend.md, Abschnitte "Billing Configuration" und
"Automated Billing Process" - Begründung: Beschreibt die Vertragsabrechnung aus
Entwicklersicht, einschließlich Kontingent- und Zählerlogik.
Prüfidee: Ein Vertrag mit `BillingIntervalKind = Quarterly` und `BillingIntervalDuration = 1` erzeugt
beim Lauf der automatischen Fakturierung eine Rechnung über einen Zeitraum von drei Monaten.
Tracelinks: SyRS-019
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-008
Titel: Mehrstufiges Mahnwesen
Ebene: StRS
Typ: funktional
Akteur: Forderungsmanagement / Buchhaltung
Vorbedingung: Offene, fällige Rechnung; Benutzer hat Zugriff auf das Mahnmodul
Fakt: `DunningRunBL.ExecuteDunningRun()` erhöht die Mahnstufe einer Rechnung entlang der Kette
`DunningLevel.None → Level1 → Level2 → Level3` und protokolliert je Stufe Datum
(`DunningLevel1Date` …) und auslösenden Benutzer (`DunningLevel1Employee` …).
`DunningRunBL.ResetDunningRun()` setzt die jeweils erreichte Stufe wieder zurück.
`DunningBL` kennt zusätzlich einen Mahnstopp (`UpdateDunningStopAndInfo` mit
`dunningStopBegin`/`dunningStopEnd`).
Aussage: Das System soll ein mehrstufiges Mahnverfahren mit maximal drei Mahnstufen unterstützen, jede
Stufenerhöhung mit Datum und auslösendem Benutzer protokollieren, Mahnläufe zurücknehmen können
und einen zeitlich begrenzten Mahnstopp je Objekt erlauben.
Ergebnis: Eine überfällige Rechnung wird je Mahnlauf um genau eine Stufe erhöht (max. Stufe 3);
ein zurückgenommener Mahnlauf stellt den Vorzustand her.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs, Z. 253-268
(`switch (invoice.DunningLevel)` mit den Übergängen None→Level1→Level2→Level3) - Begründung:
Die Statusmaschine des Mahnwesens ist im Code implementiert und begrenzt die Stufenzahl.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs,
`ResetDunningRun()` (Z. 495-535) - Begründung: Belegt die Rücknahmefähigkeit als eigenständige
Fachfunktion mit Rücksetzung von Datum und Bearbeiter.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs,
`UpdateDunningStopAndInfo()` (Z. 392) - Begründung: Mahnstopp mit Zeitraum ist als
persistierte Eigenschaft implementiert.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs,
`CalculateDunningStatistics()` (Z. 207-230) mit Auswertung genau der Stufen 0-3 - Begründung:
Bestätigt die Stufenanzahl über die Auswertungslogik.
Prüfidee: Eine Rechnung in Stufe 3 wird durch einen weiteren Mahnlauf nicht weiter erhöht; nach
`ResetDunningRun` steht die Rechnung wieder auf der vorherigen Stufe mit geleerten
Stufenfeldern.
Tracelinks: SyRS-020
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-009
Titel: Beschaffungsprozess mit elektronischer Lieferantenanbindung
Ebene: StRS
Typ: funktional / Schnittstelle
Akteur: Einkauf, Lieferant
Vorbedingung: Lieferanten-EDI-Konfiguration hinterlegt
Fakt: `CentronObjectKindNumeric` definiert die Lieferantenbelegarten Anfrage (15), Bestellung (7),
Wareneingang (8), WE-Kalkulation (18) und Lieferantengutschrift (148); `IsSupplierReceipt()`
fasst sie zusammen. Unter `src/backend/Centron.BL/EDI/` existieren Implementierungen für ALSO,
AlsoCH, Alltron, Komsa, Concerto, EGIS, OpenTrans 2.1 und ZUGFeRD. `EdiDataType` und
`EDIConnectionObjectKind` definieren Formate und Dokumentarten typisiert.
Aussage: Das System soll den Beschaffungsprozess über eigene Lieferantenbelegarten abbilden und
Bestellungen, Auftragsbestätigungen, Lieferscheine und Rechnungen elektronisch mit
Distributoren austauschen können.
Ergebnis: Eingehende EDI-Dokumente aktualisieren die zugehörigen Bestellungen bzw. erzeugen Folgebelege;
ausgehende Bestellungen werden im vereinbarten Format übertragen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, Z. 139-147 und
`IsSupplierReceipt()` (Z. 289-301) - Begründung: Die Lieferantenbelegarten sind typisiert
festgelegt und werden zur Laufzeit klassifiziert.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs, Z. 12-27 und
src/webservice/Centron.WebServices.Core/Entities/EDI/EDIConnectionObjectKind.cs, Z. 12-22 -
Begründung: Format- und Dokumentartenumfang sind als Enums durchgesetzt und Teil des
Web-Service-Vertrags (`[EnumMember]`).
- [SEKUNDÄR] src/backend/Centron.BL/EDI/ (Unterverzeichnisse ALSO, Alltron, AlsoCH, Concerto, EGIS, Komsa,
Opentrans21, Zugferd, SupplierEDI, Import) - Begründung: Die Verzeichnisstruktur belegt den
Umfang der real unterstützten Lieferantenformate.
- [KONTEXT] docs/reference/edi/edi-architecture.md, Tabelle "Document Types Supported" - Begründung:
Ordnet je Lieferant zu, welche Dokumentarten unterstützt werden.
Prüfidee: Für einen konfigurierten Lieferanten wird ein OpenTrans-2.1-Auftragsbestätigungsdokument
eingelesen und der zugehörigen Bestellung zugeordnet; das Ergebnis erscheint im EDI-Protokoll.
Tracelinks: SyRS-021, SyRS-022
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-010
Titel: Self-Service-Portal für Endkunden
Ebene: StRS
Typ: funktional
Akteur: Kunde des Betreibers (Web-Account)
Vorbedingung: Web-Account im Adressstamm angelegt und aktiv
Fakt: `src/nexus/CentronNexus` enthält die Bereiche `WebCart` (Shop), `WebOffer` (Angebotsansicht mit
Annahme), `ServiceBoard` (Ticketsicht), `DocumentSigning` (digitale Unterschrift) und
`Management`. `WebAccountAuthenticator`/`WebAccountBL.LoginWithWebAccount()` implementieren
eine eigene Anmeldung für Kundenkonten. `WebReceiptState` kennt die Werte
`AcceptFullWebReceipt`, `AcceptWebReceiptWithChangeRequests`, `Rejected`, `WebOfferSign`,
`WebOfferSignedWithoutSignature`.
Aussage: Das System soll Endkunden des Betreibers einen webbasierten Zugang bereitstellen, über den sie
Angebote einsehen, annehmen, ablehnen oder mit Änderungswünschen versehen, Dokumente digital
unterschreiben, Tickets einsehen und aus einem Sonderpreiskatalog bestellen können.
Ergebnis: Die Kundenentscheidung (Annahme/Ablehnung/Unterschrift) wird am Beleg gespeichert und ist im
ERP sichtbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 5924-5928 (Auswertung von
`WebReceiptState.AcceptFullWebReceipt` / `AcceptWebReceiptWithChangeRequests` / `Rejected`)
und Z. 6302, 6360 (`WebOfferSign`, `WebOfferSignedWithoutSignature`) - Begründung: Die
Kundenrückmeldung aus dem Portal wird im Backend als Belegzustand verarbeitet.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs,
`LoginWithWebAccount()` (Z. 54-95) - Begründung: Eigener Anmeldeweg für Kundenkonten inkl.
Aktivitäts- und Sperrprüfung von Kontakt, Adresse und Kunde.
- [SEKUNDÄR] src/nexus/CentronNexus/ (Verzeichnisse `WebCart`, `WebOffer`, `ServiceBoard`,
`DocumentSigning`) sowie `docker/deploy/appsettings.json` Abschnitt `WebAccount` -
Begründung: Belegt die im Portal umgesetzten Fachbereiche und ihre Konfigurierbarkeit.
- [KONTEXT] README.md, Abschnitt "Contributing / 1. WebCart": "The webcart is a feature primarily intended
for the customers of our customers … The available articles come from the customers
'Sonderpreise'" - Begründung: Nennt Zielgruppe und Preisquelle des Shops explizit.
Prüfidee: Ein Web-Account kann sich anmelden, ein freigegebenes Angebot einsehen und annehmen; der
Belegzustand im ERP wechselt entsprechend.
Tracelinks: SyRS-023
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-011
Titel: Elektronische Rechnungsstellung nach ZUGFeRD/XRechnung
Ebene: StRS
Typ: funktional / Schnittstelle
Akteur: Rechnungsstellung, Rechnungsempfänger (auch öffentliche Auftraggeber)
Vorbedingung: Einstellung `IsZugferdInvoiceActive` aktiviert
Fakt: `ApplicationSettingID` enthält u. a. `IsZugferdInvoiceActive` (10028),
`IsZugferdXRechnungActive`, `AppendZugferdInvoiceXmlToMails`, `ActiveZugferdInterface`,
`ZugferdExportPreferMandatorNameOverBranchName`, `ZugferdExportDontExportArticleCode`,
`ZugferdExportDontExportEanCode`, `ZugferdSellerContactPersonKind`. Die Beschreibung zu
`IsZugferdXRechnungActive` lautet: "If this settings is active, ZUGFeRD PDF file will contain
new version of XML file (XRechnung 2.1)." Unter `src/backend/Centron.BL/EDI/Zugferd/` liegen
`ZUGFeRD_BL.cs` und `ZugferdParseBL.cs`.
Aussage: Das System soll Rechnungen zusätzlich zum PDF in maschinenlesbarer Form nach ZUGFeRD bzw.
XRechnung erzeugen, den Umfang der übertragenen Felder konfigurierbar halten und eingehende
ZUGFeRD-Rechnungen einlesen können.
Ergebnis: Eine erzeugte Rechnung enthält bei aktivierter Einstellung ein eingebettetes, standardkonformes
XML; der Versand per E-Mail kann das XML zusätzlich anhängen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs, Z. 223
(`IsZugferdInvoiceActive = 10028`) und
src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs,
Z. 108-111, 506-514, 770 - Begründung: Die Konfigurationsschalter sind typisiert definiert und
steuern das Laufzeitverhalten der Rechnungserzeugung.
- [PRIMÄR] src/backend/Centron.BL/EDI/Zugferd/ZUGFeRD_BL.cs und ZugferdParseBL.cs - Begründung: Erzeugung
und Parsen sind als eigene Fachlogik implementiert (Ein- und Ausgangsrichtung).
- [SEKUNDÄR] docs/reference/zugferd-feldzuordnung-anwender.md (28 005 Bytes) und
docs/reference/zugferd-field-mapping.md (24 769 Bytes) - Begründung: Detaillierte
Feldzuordnungstabellen belegen den fachlichen Abdeckungsgrad der Schnittstelle.
- [KONTEXT] Commit `7d62212022` "Fix: Correct discount calculation to retain sign for ZUGFeRD total check
integrity (#112)" - Begründung: Belegt, dass die Summenkonsistenz des ZUGFeRD-Dokuments aktiv
validiert wird.
Prüfidee: Bei aktivierter Einstellung enthält das erzeugte Rechnungs-PDF ein eingebettetes XML, das die
KOSIT-Validierung für XRechnung besteht.
Tracelinks: SyRS-024
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-012
Titel: Unterstützung datenschutzrechtlicher Pflichten (DSGVO)
Ebene: StRS
Typ: Sicherheit / rechtlich
Akteur: Datenschutzverantwortlicher, Administrator
Vorbedingung: Benutzer besitzt das Recht `DsgvoModule.ACCESS_CLEANUP_DATABASE`
Fakt: Es existieren ein eigenes DSGVO-Modul (`src/backend/Centron.BL/Administration/Documents/Dsgvo/`,
`DsgvoBL`) mit Verwaltung von Auftragsverarbeitungsverträgen (`OrderProcessingContract`,
Objektart 7600085) sowie eine Datenbereinigung (`DataSecurityBL`) mit alters- und
objektartabhängigen Statistiken und einer Löschfunktion für Kontakte
(`DsgvoDeleteRightDeleteContacts`). Die UI führt ein eigenes Modul
`Modules.Administration.DSGVO`.
Aussage: Das System soll die Erfüllung datenschutzrechtlicher Pflichten unterstützen, insbesondere die
Verwaltung von Auftragsverarbeitungsverträgen, die Auswertung löschbarer Altdatenbestände und
die gezielte Löschung personenbezogener Kontaktdaten, jeweils gebunden an ein eigenes Recht.
Ergebnis: Ein Datenschutzverantwortlicher kann Altdatenbestände auswerten und Kontaktdaten löschen;
Auftragsverarbeitungsverträge sind je Kunde dokumentiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs,
`DataSecurityExecuteCleanUp()` (Z. 63-68): Prüfung
`currentUser.HasUserRight(UserRightsConst.DsgvoModule.ACCESS_CLEANUP_DATABASE)` und
`ModuleFeatures.IsDsgvoDatabaseCleanupAvailable` - Begründung: Rechte- und Feature-Bindung der
Bereinigung ist serverseitig implementiert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Documents/Dsgvo/DsgvoBL.cs (Verwaltung von
`OrderProcessingContractTemplate` inkl. Audit-Feldern `CreatedBy`/`ChangedBy`) - Begründung:
Auftragsverarbeitungsverträge sind als persistierte, revisionsfähige Objekte implementiert.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, Meldungstexte wie
"Es gibt {n} CRM-Einträge die älter als {Datum} sind." - Begründung: Zeigt die
Löschfristensystematik aus Anwendersicht.
- [KONTEXT] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Namespace-Import
`Modules.Administration.DSGVO` - Begründung: Belegt das DSGVO-Modul als eigenständigen
Einstiegspunkt in der Oberfläche.
Prüfidee: Ein Benutzer ohne `ACCESS_CLEANUP_DATABASE` erhält bei Aufruf der Bereinigung die Meldung
"Insufficient rights!".
Tracelinks: SyRS-025
Konsolidierung: nein
Status: belegt; Workaround
Anmerkung: Siehe SyRS-025 - die Methode `DataSecurityExecuteCleanUp` führt nach der Rechteprüfung keine
Löschoperation aus, sondern gibt unmittelbar Erfolg zurück.
```
---
```
ID: StRS-013
Titel: Nachvollziehbarkeit von Geschäftsvorfällen
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Sicherheit / Verantwortlichkeit)
Akteur: Revision, Fachbereichsleitung
Vorbedingung: Änderung an einem Beleg, Ticket oder an Rechten
Fakt: `ReceiptBase` führt die Felder `CreatedByI3D`, `CreatedAt`, `CreatedThroughApplicationVersion`,
`ChangedByI3D`, `ChangedAt`, `ChangedThroughApplicationVersion`, `ChangedThroughApplication`
und `Version`. `ReceiptBL.WriteReceiptLogs()` schreibt für jede geänderte Kontingent- und
Bankverbindungseigenschaft einen eigenen Protokolleintrag über `ReceiptLogBL`. `AppRightsBL`
protokolliert jede Rechte-/Gruppenänderung als `AppRightLog` mit Benutzer, Zeitpunkt und
Anwendungsversion. `AccessTokenLogBL` protokolliert Tokennutzung inkl. API-Methode und
IP-Adresse.
Aussage: Das System soll für geschäftsrelevante Objekte (Belege, Rechte, Zugriffstoken) festhalten, wer
wann mit welcher Anwendungsversion welche Änderung vorgenommen hat, und diese Historie
auswertbar bereitstellen.
Ergebnis: Zu jedem Beleg, jeder Rechteänderung und jeder Tokennutzung ist der Verursacher und der
Zeitpunkt ermittelbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Z. 46-52 (Audit-Felder
inkl. Anwendungsversion) - Begründung: Die Nachvollziehbarkeitsfelder sind Teil der
persistierten Basisklasse aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, `WriteBaseLog()` (Z. 762-781)
mit `CreatedByI3D`, `CreatedDate`, `CreatedVersion` - Begründung: Rechteänderungen werden
zwingend protokolliert; die Methode wird aus allen ändernden Operationen aufgerufen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `WriteReceiptLogs()` (ab Z. 10313) -
Begründung: Feldgenaue Änderungsprotokollierung für abrechnungsrelevante Belegattribute.
- [SEKUNDÄR] docs/guides/database/database-conventions.md, Abschnitt 2 "Standard Tracking Columns"
(`CreatedByI3D`, `CreatedDate`, `ChangedByI3D`, `ChangedDate`, Soft-Delete-Spalten) -
Begründung: Verbindliche Konvention für alle neuen Tabellen.
Prüfidee: Nach Änderung eines Belegs sind `ChangedByI3D`, `ChangedAt` und
`ChangedThroughApplicationVersion` aktualisiert; nach Entzug eines Rechts existiert ein
`AppRightLog`-Eintrag mit Text "Recht … der Gruppe … entzogen".
Tracelinks: SyRS-008, SyRS-026, SyRS-030
Konsolidierung: nein
Status: belegt
```
---
```
ID: StRS-014
Titel: Deutschsprachiger Zielmarkt mit optionaler englischer Oberfläche
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Gebrauchstauglichkeit)
Akteur: Endanwender
Vorbedingung: keine
Fakt: Zu jeder Ressourcendatei `LocalizedStrings.resx` existiert genau eine Übersetzungsdatei
`LocalizedStrings.en.resx` (Backend, WPF-Client, Controls); im Nexus entsprechend
`SharedResource.resx` / `SharedResource.en-US.resx`. Fehlermeldungen im Backend werden in
deutscher Sprache erzeugt (z. B. "Sie haben nicht genügend Rechte um eine Gruppe anlegen zu
können.", "Die maximale Anzahl an Lizenzen wurde erreicht.").
Aussage: Das System soll Deutsch als Standardsprache der Oberfläche und aller Anwendermeldungen führen
und zusätzlich Englisch als vollständige Alternativsprache bereitstellen.
Ergebnis: Anwender erhalten alle Meldungen in Deutsch; bei englischer Spracheinstellung stehen
übersetzte Ressourcen bereit.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Resources/LocalizedStrings.resx und LocalizedStrings.en.resx;
src/centron/Centron.WPF.UI/Resources/LocalizedStrings.resx und .en.resx;
src/shared/Centron.Controls/Resources/LocalizedStrings.resx und .en.resx -
Begründung: Das durchgängige Paar Basis-/Englisch-Ressource ist der technische Mechanismus,
der die Zweisprachigkeit trägt.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 357, 389, 396 (deutsche
Fehlermeldungen im Backend) - Begründung: Belegt Deutsch als Sprache der fachlichen Meldungen
auch außerhalb der Oberfläche.
- [SEKUNDÄR] ResXManager.config.xml (Repository-Wurzel) - Begründung: Belegt ein etabliertes Werkzeug zur
Ressourcenpflege und damit einen gelebten Übersetzungsprozess.
- [KONTEXT] docs/getting-started/general-structure.md, Abschnitt "German-First Language Policy":
"Because c-entron.NET is developed specifically for the German market, all user-facing content
must adhere to the following guidelines" - Begründung: Erklärt die Marktausrichtung als
bewusste Vorgabe.
Prüfidee: Für jeden Schlüssel in `LocalizedStrings.resx` existiert ein Eintrag in
`LocalizedStrings.en.resx`; die Oberfläche zeigt bei Umschaltung auf Englisch keine deutschen
Restbestände in geprüften Masken.
Tracelinks: SyRS-028
Konsolidierung: Kandidat: Die Lokalisierung ist auf vier voneinander unabhängige Ressourcensätze verteilt
(Centron.BL, Centron.WPF.UI, Centron.Controls, CentronNexus) - im Zielsystem ist ein
gemeinsamer Ressourcenbestand zu prüfen.
Status: belegt
```
---
```
ID: StRS-015
Titel: Betrieb wahlweise als On-Premises-Installation oder containerisierter Dienst
Ebene: StRS
Typ: nicht-funktional (ISO/IEC 25010: Übertragbarkeit)
Akteur: Betreiber / IT-Administrator
Vorbedingung: Microsoft SQL Server verfügbar
Fakt: Es existieren nebeneinander (a) ein Windows-Installer-Projekt
(`deployment/WixSharpInstaller`), (b) ein Windows-Dienst-Host
(`src/webservice/Centron.Host.WindowsService`), (c) ein Konsolen-Host
(`src/webservice/Centron.Host.Console`) und (d) Container-Definitionen unter `docker/`
(u. a. `docker/Dockerfile` für den Nexus-Host auf Alpine Linux, `docker/c-entron-webservice`,
`docker/compose`). `docs/guides/services/web-service-on-linux.md` beschreibt den Linux-Betrieb.
Der Nexus-Container setzt `TZ=Europe/Berlin` und
`DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false`.
Aussage: Das System soll sowohl als klassische Windows-Installation (Client, Windows-Dienst) als auch
als containerisierter Dienst unter Linux betreibbar sein, wobei Zeitzone und
Globalisierungsverhalten für den deutschen Markt vorkonfiguriert sind.
Ergebnis: Der Web-Service und der Nexus-Webclient sind auf Windows und in Linux-Containern lauffähig;
der Rich Client bleibt Windows-gebunden.
Belege:
- [PRIMÄR] docker/Dockerfile, Z. 1-30 (`dotnet publish CentronNexus.Host.csproj --self-contained`,
Runtime-Image `dotnet/runtime:10.0.5-alpine3.23`, `ENV TZ=Europe/Berlin`,
`ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false`) - Begründung: Der Containerbetrieb ist
vollständig als reproduzierbarer Build definiert, inkl. der Kulturvoraussetzungen.
- [PRIMÄR] src/webservice/Centron.Host.WindowsService/ (Projekt inkl. eigener nlog.config) und
deployment/WixSharpInstaller/WixSharpInstaller.csproj - Begründung: Belegt den parallelen
klassischen Installationspfad.
- [SEKUNDÄR] docker/deploy/appsettings.json, Abschnitte `Host.Url`, `Host.LinuxCertificatePath`,
`Host.LinuxCertificatePassword`, `CentronWebService.Url` - Begründung: Konfigurationsschalter
speziell für den Linux-/Containerbetrieb inkl. TLS-Zertifikat.
- [KONTEXT] docs/guides/services/web-service-on-linux.md - Begründung: Beschreibt den Linux-Betrieb als
unterstützten Weg.
Prüfidee: Der Nexus-Host startet aus dem Container-Image und beantwortet Anfragen unter der in
`Host.Url` konfigurierten Adresse; der Web-Service läuft parallel als Windows-Dienst.
Tracelinks: SyRS-031, SyRS-032
Konsolidierung: nein
Status: belegt
```
---
## 5. Abgrenzungen auf StRS-Ebene
Folgende Bereiche sind in der Codebasis erkennbar vorhanden, wurden in dieser Iteration aber **nicht** zu
eigenen Stakeholder-Anforderungen ausgearbeitet (siehe `Analysebericht.md`, Abschnitt Lücken):
Lagerwirtschaft/Inventur, Produktion/PLM, Kassenbuch, Online-Banking/Zahlungsverkehr, CRM-Kampagnen,
Projektmanagement, Asset-/Inventarmanagement (Riversuite/DocuBoard), TAPI-Telefonie, Reportengine,
Mailscanner, Statistik/Dashboards, KI-Chat-Modul.
@@ -0,0 +1,149 @@
# Traceability-Matrix
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48`, Version `2.0.2611-alpha`
**Datum:** 2026-08-25
Die Matrix stellt die Forward- und Backward-Traceability zwischen den drei Spezifikationsebenen her.
Die in `StRS.md`, `SyRS.md` und `SwRS.md` je Anforderung im Feld `Tracelinks` angegebenen Verweise wurden
zu einer symmetrischen Relation zusammengeführt (siehe `Analysebericht.md`, Abschnitt 6.3).
---
## 1. Haupttabelle (eine Zeile je SyRS-Anforderung)
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (Leitbeleg) |
|---|---|---|---|
| StRS-001 | SyRS-001 Belegarten und Klassifikation | SwRS-003, SwRS-004, SwRS-006, SwRS-008 | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` Z. 20-264, 266-301 |
| StRS-001, StRS-013 | SyRS-002 Belegstatusmodell | SwRS-015, SwRS-016 | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` Z. 6-14; `ReceiptBL.cs` Z. 796-797, 4936-4950 |
| StRS-001 | SyRS-003 Belegweiterführung | SwRS-013, SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs` Z. 279-297, 673 |
| StRS-001, StRS-002 | SyRS-004 Belegnummernvergabe | SwRS-014 | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs` Z. 62-134 |
| StRS-002, StRS-003 | SyRS-005 Filialbeschränkung | SwRS-016 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 10251-10295 |
| StRS-003 | SyRS-006 Serverseitige Rechtedurchsetzung | SwRS-002, SwRS-016, SwRS-017, SwRS-018, SwRS-023 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 644-709 |
| StRS-003 | SyRS-007 Verwaltung von Rechtegruppen | SwRS-016 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 348-404, 261-278, 563-612 |
| StRS-003, StRS-013 | SyRS-008 Protokollierung von Rechteänderungen | SwRS-007 | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs` Z. 762-857 |
| StRS-003, StRS-004 | SyRS-009 Ticketbasierte API-Authentifizierung | SwRS-010, SwRS-023 | `src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs` Z. 22-136 |
| StRS-003, StRS-004 | SyRS-010 Authentifizierungsverfahren | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs` Z. 44-188 |
| StRS-003 | SyRS-011 Zwei-Faktor-Authentifizierung | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs` Z. 32-120 |
| StRS-003 | SyRS-012 Kontosperrung und -deaktivierung | SwRS-009 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` Z. 157-218 |
| StRS-003, StRS-004, StRS-013 | SyRS-013 API-Access-Tokens | SwRS-011, SwRS-023 | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs` Z. 377-487 |
| StRS-004 | SyRS-014 Lizenzprüfung beim Login | SwRS-010, SwRS-018 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` Z. 68-155; `LicenseManager.cs` Z. 219-236 |
| StRS-004 | SyRS-015 Lizenzanzahlbegrenzung | SwRS-010 | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs` Z. 258-302 |
| StRS-004 | SyRS-016 Ticketgültigkeitsdauer | SwRS-010, SwRS-019 | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs` Z. 26-28, 113-164 |
| StRS-005 | SyRS-017 Ticketabschluss mit Checklistenprüfung | SwRS-015 | `src/backend/Centron.BL/Sales/Support/UpdateHelpdeskBL.cs` Z. 492-518 |
| StRS-006, StRS-013 | SyRS-018 Schutz abgerechneter Zeiten | SwRS-016 | `src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs` Z. 553-605 |
| StRS-007 | SyRS-019 Vertragsabrechnungsintervalle | SwRS-012, SwRS-022 | `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs` Z. 1098-1130, 1355-1373 |
| StRS-008, StRS-013 | SyRS-020 Mahnläufe und Rücknahme | SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs` Z. 253-268, 495-535 |
| StRS-009 | SyRS-021 EDI-Formate und Dokumentarten | SwRS-008, SwRS-015 | `src/webservice/Centron.WebServices.Core/Entities/EDI/EdiDataType.cs` Z. 12-27; `EDIConnectionObjectKind.cs` Z. 12-22 |
| StRS-009, StRS-013 | SyRS-022 EDI-Protokollierung | SwRS-002 | `src/backend/Centron.Interfaces/EDI/EDILogState.cs` Z. 9-19 |
| StRS-003, StRS-010 | SyRS-023 Portalzugang für Kundenkonten | SwRS-009, SwRS-017 | `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs` Z. 54-95 |
| StRS-011 | SyRS-024 Elektronische Rechnung ZUGFeRD/XRechnung | SwRS-012, SwRS-013, SwRS-019 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 3272-3292; `ApplicationSettingDefinitions.cs` Z. 108-111 |
| StRS-012 | SyRS-025 DSGVO-Auswertung und -Löschung | SwRS-016 | `src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs` Z. 34-68, 377, 787 |
| StRS-001, StRS-013 | SyRS-026 Belegversionierung | SwRS-003, SwRS-005, SwRS-007 | `src/backend/Centron.DAO/Mappings/Sales/Receipts/Invoices/ReceiptInvoiceVersionMaps.cs` Z. 5-20 |
| StRS-013 | SyRS-027 Optimistische Sperre | SwRS-024 | `src/backend/Centron.Entities/…/ReceiptBase.cs` Z. 55; `ReceiptBL.cs` Z. 4939-4940 |
| StRS-014 | SyRS-028 Mehrsprachigkeit | SwRS-021 | `src/backend/Centron.BL/Resources/LocalizedStrings.resx` / `LocalizedStrings.en.resx` |
| StRS-004, StRS-015 | SyRS-029 Automatisches Datenbank-Update | SwRS-020 | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs` Z. 39-130 |
| StRS-013, StRS-015 | SyRS-030 Betriebsprotokollierung | SwRS-002 | `src/webservice/Centron.Host.WindowsService/nlog.config` |
| StRS-015 | SyRS-031 Auslieferungs- und Betriebsformen | SwRS-020 | `version.json`; `Directory.Build.props` Z. 6-40; `docker/Dockerfile` |
| StRS-015 | SyRS-032 Zwei Zugriffswege des Clients | SwRS-001, SwRS-018 | `src/backend/Centron.Interfaces/Administration/Connections/CentronConnectionType.cs` Z. 6-12 |
---
## 2. Abdeckungsmatrix StRS → SyRS (Forward)
| StRS-ID | Titel | abgedeckt durch SyRS |
|---|---|---|
| StRS-001 | Durchgängige Belegkette im Vertriebsprozess | SyRS-001, SyRS-002, SyRS-003, SyRS-004, SyRS-026 |
| StRS-002 | Mandanten- und Filialorganisation | SyRS-004, SyRS-005 |
| StRS-003 | Rollenbasierte Zugriffssteuerung | SyRS-005, SyRS-006, SyRS-007, SyRS-008, SyRS-009, SyRS-010, SyRS-011, SyRS-012, SyRS-013, SyRS-023 |
| StRS-004 | Lizenzabhängiger Funktionsumfang | SyRS-009, SyRS-010, SyRS-013, SyRS-014, SyRS-015, SyRS-016, SyRS-029 |
| StRS-005 | Serviceprozess über Helpdesk-Tickets | SyRS-017 |
| StRS-006 | Leistungserfassung und Abrechnung | SyRS-018 |
| StRS-007 | Vertrags- und Abonnementgeschäft | SyRS-019 |
| StRS-008 | Mehrstufiges Mahnwesen | SyRS-020 |
| StRS-009 | Beschaffung und Lieferantenintegration | SyRS-021, SyRS-022 |
| StRS-010 | Self-Service-Portal für Endkunden | SyRS-023 |
| StRS-011 | Elektronische Rechnungsstellung | SyRS-024 |
| StRS-012 | Datenschutzkonformität (DSGVO) | SyRS-025 |
| StRS-013 | Nachvollziehbarkeit von Geschäftsvorfällen | SyRS-002, SyRS-008, SyRS-013, SyRS-018, SyRS-020, SyRS-022, SyRS-026, SyRS-027, SyRS-030 |
| StRS-014 | Deutschsprachiger Zielmarkt | SyRS-028 |
| StRS-015 | Betriebsmodelle | SyRS-029, SyRS-030, SyRS-031, SyRS-032 |
**Ergebnis:** Alle 15 StRS-Anforderungen sind durch mindestens eine SyRS-Anforderung abgedeckt.
---
## 3. Abdeckungsmatrix SwRS → SyRS (Backward)
| SwRS-ID | Titel | konkretisiert SyRS |
|---|---|---|
| SwRS-001 | Schichtenmodell mit doppelter Datenzugriffsimplementierung | SyRS-032 |
| SwRS-002 | Einheitliches Ergebnis- und Fehlermodell | SyRS-006, SyRS-022, SyRS-030 |
| SwRS-003 | Doppelter Persistenzpfad für Belege | SyRS-001, SyRS-026 |
| SwRS-004 | Zweischichtiges Datenbankschema | SyRS-001, SyRS-026 |
| SwRS-005 | Versionstabellen als strukturgleiche Kopien | SyRS-026 |
| SwRS-006 | Primär-/Fremdschlüsselkonvention I3D | SyRS-001 |
| SwRS-007 | Standardisierte Nachverfolgungsspalten | SyRS-008, SyRS-026 |
| SwRS-008 | Rückwärtskompatible Enum-Erweiterung | SyRS-001, SyRS-021 |
| SwRS-009 | Speicherung und Prüfung von Kennwörtern | SyRS-010, SyRS-011, SyRS-012, SyRS-023 |
| SwRS-010 | Erzeugung und Struktur von Sitzungstickets | SyRS-009, SyRS-014, SyRS-015, SyRS-016 |
| SwRS-011 | Erzeugung und Speicherung von Access-Tokens | SyRS-013 |
| SwRS-012 | Preisberechnung mit definierter Rundung | SyRS-019, SyRS-024 |
| SwRS-013 | Umsatzsteuerberechnung | SyRS-003, SyRS-024 |
| SwRS-014 | Nebenläufigkeitssichere Nummernvergabe | SyRS-004 |
| SwRS-015 | Belegartspezifische Logik (Strategiemuster) | SyRS-002, SyRS-003, SyRS-017, SyRS-020, SyRS-021 |
| SwRS-016 | Rechteprüfungen in der Geschäftslogik | SyRS-002, SyRS-005, SyRS-006, SyRS-007, SyRS-018, SyRS-025 |
| SwRS-017 | Zwischenspeicherung von Benutzerrechten | SyRS-006, SyRS-023 |
| SwRS-018 | Rechte-/lizenzabhängige Modulregistrierung | SyRS-006, SyRS-014, SyRS-032 |
| SwRS-019 | Zweigeteilte Einstellungsverwaltung | SyRS-016, SyRS-024 |
| SwRS-020 | Skriptbasierte Datenbankmigration | SyRS-029, SyRS-031 |
| SwRS-021 | Lokalisierung über .resx-Ressourcen | SyRS-028 |
| SwRS-022 | Umrechnung von Abrechnungsintervallen | SyRS-019 |
| SwRS-023 | Interceptor-Kette des Web-Service | SyRS-006, SyRS-009, SyRS-013 |
| SwRS-024 | Explizite Belegsperre | SyRS-027 |
**Ergebnis:** Alle 24 SwRS-Anforderungen referenzieren mindestens eine existierende SyRS-Anforderung.
---
## 4. SyRS-Anforderungen ohne SwRS-Konkretisierung
Alle 32 SyRS-Anforderungen sind durch mindestens eine SwRS-Anforderung konkretisiert. Die geringste
Konkretisierungstiefe weisen auf:
| SyRS-ID | Anzahl SwRS | Bemerkung |
|---|---|---|
| SyRS-022 (EDI-Protokollierung) | 1 (SwRS-002) | Die EDI-Verarbeitungslogik selbst wurde nicht auf SwRS-Ebene ausgearbeitet - siehe `Analysebericht.md`, Lücke L-03. |
| SyRS-025 (DSGVO) | 1 (SwRS-016) | Löschmechanik nicht ausgearbeitet; offene Frage H-04. |
| SyRS-027 (Optimistische Sperre) | 1 (SwRS-024) | ausreichend |
| SyRS-028 (Mehrsprachigkeit) | 1 (SwRS-021) | ausreichend |
| SyRS-031 (Auslieferungsformen) | 1 (SwRS-020) | Build-/Signaturkette nicht auf SwRS-Ebene ausgearbeitet. |
---
## 5. Konsolidierungskandidaten (Redundanzregister)
Zusammenstellung aller Anforderungen, deren Feld `Konsolidierung` einen Kandidaten benennt. Diese Fälle sind
bei der Zielarchitektur vorrangig zu entscheiden.
| Nr. | Betroffene Anforderungen | Redundante fachliche Funktion | Fundstellen |
|---|---|---|---|
| K-01 | SyRS-006, SwRS-016 | Rechteprüfung eines Benutzers (4 Mechanismen) | `AppUser.HasUserRight`; `AppRightsBL.HasUserRight` (gecacht/SQL); `AppRightsBL.CheckRightsFromUser` (SQL, Menge); `AppRightsBL.GetRightsFromCurrentUser` (Objektgraph) |
| K-02 | SyRS-017 | Prüfung "Ticket abschließbar?" (3 Implementierungen, davon eine wirkungslos) | `UpdateHelpdeskBL.CanHelpdeskClose` Z. 492; `HelpdeskWebServiceBL.CanHelpdeskClose` Z. 283; `HelpdeskCloseBL.CanCloseHelpdesk` Z. 158 (`return true;`) |
| K-03 | SyRS-019, SwRS-022 | Umrechnung Abrechnungsintervall → Monate (3 Implementierungen, `Daily` abweichend) | `AutomaticFacturaBL.Contracts.cs` Z. 1104; `ReportObjectsBL.cs` Z. 272; `ReceiptToReportObjectMap.cs` Z. 354 |
| K-04 | SyRS-002 | Übergang eines Belegs nach "abgeschlossen" (4 Auslöser) | `ReceiptBL.CheckCloseReceipt` Z. 4130; `CheckCloseRMADeliverylistReceipt` Z. 4152; `UpdateReceiptStateFromPaymentCondition` Z. 8336; Zahlungssetzung Z. 4944 |
| K-05 | SyRS-005 | Filialprüfung (Anlage vs. Bearbeitung, zwei Null-Behandlungen) | `ReceiptBL.CanUserCreateReceiptsInBranch` Z. 10251; `CanUserEditReceipt` Z. 10272 |
| K-06 | SwRS-003, SwRS-004 | Belegpersistenz (modernes View-Mapping vs. Legacy-Save-Repository) | `ReceiptInvoiceMaps.cs`; `RechKopfMaps.cs`; `SaveReceiptInvoiceRepository` |
| K-07 | SwRS-009 | Hashverfahren (3 Varianten) | `SHA1Decoder` (ohne Salt); `CryptoUtils.CreatePasswordHash` (SHA-1 mit Salt); `AccessTokenBL.HashToken` (SHA-256) |
| K-08 | SwRS-001, SyRS-032 | Datenzugriff je Modul (BL- und WS-Implementierung) | alle `I*Logic` / `BL*Logic` / `WS*Logic` |
| K-09 | SwRS-002, SwRS-023 | Fehler-/Antwortmodell (2 Modelle) | `Result`/`Result<T>` vs. `Response`/`StatusCode` |
| K-10 | SwRS-019 | Anwendungseinstellungen (2 Tabellen, 2 Schlüsselenums) | `Stammdat`/`AppSettingsConst` vs. `ApplicationSettings`/`ApplicationSettingID` |
| K-11 | SwRS-020 | Datenbankmigration (2 Mechanismen) | C#-Skriptklassen vs. `SQLScriptCollection*.xaml` |
| K-12 | SyRS-028, StRS-014, SwRS-021 | Lokalisierungsressourcen (4 getrennte Sätze) | Centron.BL, Centron.WPF.UI, Centron.Controls, CentronNexus |
| K-13 | SyRS-030 | Protokollierungskonfiguration (4 getrennte Konfigurationen) | 3 × `nlog.config` + `appsettings.json` |
| K-14 | SyRS-023 | Rechtemodell (Mitarbeiter vs. Web-Account) und Kontaktmodell (`AddressContactI3D` vs. `AccountAddressContactI3D`) | `Sichtrus`/`Sichmemb` vs. `WebAccountsRights`; `WebAccountBL.LoginWithWebAccount` Z. 68/82 |
| K-15 | SyRS-024 | ZUGFeRD-Aktivierung (global vs. belegbezogen) | `InvoiceZugferdBL.IsZugferdEnabled()` vs. `ReceiptBL.GetLocalZUGFeRDSetting(receipt)` |
| K-16 | SwRS-006 | Fremdschlüsselbenennung (`…I3D` vs. historisch `…ID`) | `RechKopfMaps.cs` (`KundenID`, `AnschriftID`, `PersonID`) |
| K-17 | SwRS-012 | Preisberechnung in `double` und `decimal` | `CalculationUtils.cs` (parallele Überladungen) |
| K-18 | SwRS-015 | Zu breite Belegschnittstelle (~100 Methoden, teils mit Ausnahmen) | `IReceiptSpecificLogic` und 13 Implementierungen |
| K-19 | SwRS-024, SyRS-027 | Sperrmechanismen (pessimistisch `AssetLockBL` vs. optimistisch `ConcurrencyControlGuid`) | `InvoiceSpecificLogic.TryLockReceipt`; `ReceiptBase.ConcurrencyControlGuid` |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 17 (Lauf K)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:31+02:00
- **Endzeit:** 2026-08-25T20:36:06+02:00
- **Dauer gesamt:** 00:36:35 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:36:33 (`duration_ms`) — API: 00:33:43
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-2603`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 174
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.191 Input-/25 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 128 |
| Output-Tokens | 173.802 (davon 11.712 Thinking-Tokens) |
| Cache-Write-Tokens | 411.167 |
| Cache-Read-Tokens | 12.971.068 |
| Agent-Turns | 116 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 128 | 4.191 | 4.319 |
| Output-Tokens | 173.802 | 25 | 173.827 |
| Cache-Write-Tokens | 411.167 | 0 | 411.167 |
| Cache-Read-Tokens | 12.971.068 | 0 | 12.971.068 |
| Tokens gesamt | 13.556.165 | 4.216 | **13.560.381** |
**Tokens gesamt: 13.560.381** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `acecb691-99ee-4695-b41a-1d734db5d910`
- **Permission-Denials:** **0** – —
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 44.040 B | 15 Anforderungen |
| `SyRS.md` | 104.369 B | 32 Anforderungen |
| `SwRS.md` | 74.881 B | 24 Anforderungen |
| `Traceability.md` | 13.533 B | 49 Datenzeilen |
| `Hypothesen.md` | 15.981 B | 13 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 18.421 B | Domänenbegriffe |
| `Analysebericht.md` | 23.245 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **71 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 15 | 21,1 % |
| SyRS | 32 | 45,1 % |
| SwRS | 24 | 33,8 % |
| **Gesamt** | **71** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 14 | 19,7 % |
| Sicherheit | 14 | 19,7 % |
| funktional / Daten | 7 | 9,9 % |
| Daten | 4 | 5,6 % |
| Architektur | 3 | 4,2 % |
| funktional / Sicherheit | 2 | 2,8 % |
| funktional / Schnittstelle | 2 | 2,8 % |
| Sicherheit / rechtlich | 2 | 2,8 % |
| Sicherheit / Schnittstelle | 2 | 2,8 % |
| Daten / Architektur | 2 | 2,8 % |
| (18 weitere) | 19 | 26,8 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 277 |
| davon `PRIMÄR` | 174 (62,8 %) |
| davon `SEKUNDÄR` | 61 (22,0 %) |
| davon `KONTEXT` | 42 (15,2 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 71 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 18 | 25,4 % |
| Konsolidierungskandidaten | 25 | 35,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (35 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 71 von 71 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(174 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2023261,"num_turns":116,"stop_reason":"end_turn","session_id":"acecb691-99ee-4695-b41a-1d734db5d910","total_cost_usd":14.947209999999998,"usage":{"input_tokens":128,"cache_creation_input_tokens":411167,"cache_read_input_tokens":12971068,"output_tokens":173802,"output_tokens_details":{"thinking_tokens":11712},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":411167,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1566,"cache_read_input_tokens":410588,"cache_creation_input_tokens":579,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":579},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4191,"outputTokens":25,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004316,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":128,"outputTokens":173802,"cacheReadInputTokens":12971068,"cacheCreationInputTokens":411167,"webSearchRequests":0,"costUSD":14.942893999999999,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Alle sieben Ergebnisdateien sind erstellt; die Codebasis ist unverändert (`git status` leer).\n\n## Ergebnis\n\n**Ausgabeverzeichnis:** `01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\\Ergebnisse\\`\n\n| Datei | Zeilen | Inhalt |\n|---|---|---|\n| `StRS.md` | 661 | 15 Stakeholder-Anforderungen |\n| `SyRS.md` | 1493 | 32 Systemanforderungen (5 explizit ISO/IEC 25010 zugeordnet) |\n| `SwRS.md` | 1108 | 24 Softwareanforderungen |\n| `Traceability.md` | 149 | Haupttabelle, 2 Abdeckungsmatrizen, Redundanzregister K-01…K-19 |\n| `Hypothesen.md` | 325 | 11 offene Fragen mit fehlender Information |\n| `Glossar.md` | 404 | Domänenbegriffe mit Fundstellen |\n| `Analysebericht.md` | 382 | Modulübersicht, Konsistenzcheck, Selbstbewertung |\n\n**71 Anforderungen, 277 Artefaktbelege** (62,8 % `PRIMÄR`). Konsistenzcheck maschinell ausgeführt: keine doppelten IDs, keine Anforderung ohne `PRIMÄR`-Beleg, keine Tracelinks ins Leere, alle 12 Pflichtfelder in allen 71 Anforderungen belegt.\n\n**Methodische Entscheidung, die ich hervorheben möchte:** Ich habe *keine* Anforderung mit `Status: HYPOTHESE` formuliert. Stattdessen sind nur belegbare Aussagen in die Spezifikation gegangen; alles Unbelegbare steht als offene Frage in `Hypothesen.md`. Die Entwicklerdokumentation unter `docs/` habe ich durchgängig nur als `KONTEXT` gewertet — Grund ist ein nachgewiesener Widerspruch zum Code (dokumentiert sind vier Belegzustände, implementiert sind drei).\n\n**Inhaltlich auffällig** (alle in den Anforderungen belegt und als `Workaround` markiert):\n- `// TODO the password should be salted!!!` — Kennwörter als ungesalzener SHA-1 über Codepage 1252 (`SwRS-009`)\n- `HelpdeskCloseBL.CanCloseHelpdesk()` gibt unbedingt `true` zurück, während zwei andere Stellen dieselbe Prüfung tatsächlich implementieren (`SyRS-017`, K-02)\n- `DataSecurityExecuteCleanUp()` prüft Rechte und gibt danach Erfolg zurück, ohne zu löschen (`SyRS-025`, H-04)\n- Intervall→Monate dreifach implementiert, `Daily` jeweils unterschiedlich behandelt (`SwRS-022`, K-03)\n- Belege werden über Views gelesen, aber über Legacy-Repositories in deutsche Alttabellen geschrieben (`SwRS-003`, K-06)\n\n**Wichtigste Einschränkung, die ich klar benennen muss:** Die Fachbreite ist unvollständig. Bei 16 063 C#-Dateien habe ich risikobasiert priorisiert (Sicherheit, Berechtigungen, Fakturierung) — geschätzt **55–65 % des Fachumfangs sind nicht spezifiziert** (u. a. Lagerwirtschaft, Zahlungsverkehr, Produktion, CRM, Reportengine). Als Basis für eine Neuimplementierung reicht dieser Stand noch nicht; `Analysebericht.md` Abschnitt 6.5 priorisiert die Folge-Iterationen, wobei die 12 ungenutzten Testprojekte und die 799 Migrationsskripte (kein `.sql` im Repo, Schema entsteht nur zur Laufzeit) den größten Evidenzzuwachs bei geringstem Aufwand versprechen.","ttft_ms":1803,"ttft_stream_ms":1076,"time_to_request_ms":34,"type":"result","duration_ms":2192516,"uuid":"d3eea712-8437-4e46-acfb-62ff3dadcece","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 15 | 21,1 % |
| SyRS | 32 | 45,1 % |
| SwRS | 24 | 33,8 % |
| **Gesamt** | **71** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 14 | 19,7 % |
| Sicherheit | 14 | 19,7 % |
| funktional / Daten | 7 | 9,9 % |
| Daten | 4 | 5,6 % |
| Architektur | 3 | 4,2 % |
| funktional / Sicherheit | 2 | 2,8 % |
| funktional / Schnittstelle | 2 | 2,8 % |
| Sicherheit / rechtlich | 2 | 2,8 % |
| Sicherheit / Schnittstelle | 2 | 2,8 % |
| Daten / Architektur | 2 | 2,8 % |
| (18 weitere) | 19 | 26,8 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 277 |
| davon `PRIMÄR` | 174 (62,8 %) |
| davon `SEKUNDÄR` | 61 (22,0 %) |
| davon `KONTEXT` | 42 (15,2 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 71 | 100,0 % |
| als `HYPOTHESE` gekennzeichnet | 0 | 0,0 % |
| als Workaround vermerkt | 18 | 25,4 % |
| Konsolidierungskandidaten | 25 | 35,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (35 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 71 von 71 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195913_opus5_solo_v3.6.0-2603\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:36:06.3208537+02:00
@@ -0,0 +1 @@
2026-08-25T19:59:31.9715431+02:00
@@ -0,0 +1,320 @@
# Analysebericht
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Verfahren:** Reverse Requirements Engineering nach ISO/IEC/IEEE 29148:2018, Schritte 2–6
(Scope manuell vorgegeben, Validierung durch Fachexperten steht aus)
**Vorgehen:** ausschließlich statische Analyse, keine Ausführung, keine Änderung der Codebasis
**Erstellt:** 2026-08-25
---
## 1. Untersuchungsgegenstand
### 1.1 Kennzahlen der Codebasis
| Kennzahl | Wert | Quelle |
|---|---|---|
| Projekte in der Projektmappe | 44 (davon 12 Testprojekte) | `Centron.sln` |
| C#-Dateien (ohne `bin`/`obj`) | 14 782 | Dateisystemzählung |
| XAML-Dateien | 1 233 | Dateisystemzählung |
| Razor-Dateien | 491 | Dateisystemzählung |
| Testdateien (C#) | 378 | `tests/` |
| Datenbank-Migrationsskripte (C#-Klassen) | 764 | `…/Scripts/ScriptMethods/Scripts/` |
| Zusätzliche XML-Skriptsammlungen (Altbestand) | 7 | `…/Scripts/ScriptMethods/SqlStatements/` |
| Hintergrunddienste | 33 | `…/AspNetCore/HostedServices/` |
| Registrierte anmeldefähige Anwendungen | 43 | `ApplicationKind.cs` |
| Objektarten (`CentronObjectKindNumeric`) | über 230 | `CentronObjectKindNumeric.cs` |
| Nummernkreise | 31 | `NumberGroupEnum.cs` |
| Commits | 52 135 | `git rev-list --count HEAD` |
| Erster Commit | 29.07.2014 | `git log --reverse` |
| Aktuelle Produktversion | `2.0.2611-alpha` | `version.json` |
| Zielplattform | .NET 10 (`net10.0`, `net10.0-windows`) | `.csproj`, `global.json` |
### 1.2 Komponentenübersicht
| Komponente | Pfad | Rolle | Umfang |
|---|---|---|---|
| **Centron.Entities** | `src/backend/Centron.Entities` | Domänenentitäten (NHibernate) | 1 179 Dateien in `Entities` |
| **Centron.DAO** | `src/backend/Centron.DAO` | Mappings, Repositories, `DAOSession` | 983 Mapping-, 67 Repository-Dateien |
| **Centron.BL** | `src/backend/Centron.BL` | Geschäftslogik | 959 Dateien Administration, 464 WebServices, 248 Sales, 40 Warehousing u. a. |
| **Centron.Interfaces** | `src/backend/Centron.Interfaces` | Schichtübergreifende Verträge, Aufzählungen | 283 Sales, 53 Administration, 50 Warehousing u. a. |
| **Centron.Gateway** | `src/backend/Centron.Gateway` | Fremdformat-Parser (EDI) | 32 DataExchange, 26 EDI_EGIS |
| **Centron.Common / Centron.Core** | `src/backend/`, `src/shared/` | Technische Hilfsmittel, Kryptografie, Erweiterungen | 21 Extensions u. a. |
| **Centron.WebServices.Core** | `src/webservice/Centron.WebServices.Core` | DTOs, REST-Request-Typen, Rechtekonstanten | 1 725 Entities, 615 RestRequests, 162 „EntitiesWrongPlace" |
| **Centron.Host** | `src/webservice/Centron.Host` | Anwendungsserver (ASP.NET Core), Dienstfassade, Hintergrunddienste | 71 AspNetCore-, 67 Services-Dateien |
| **Centron.Host.Console / .WindowsService** | `src/webservice/` | Betriebsarten des Anwendungsservers | klein |
| **Centron.Controllers** | `src/webservice/Centron.Controllers` | REST-Controller | 41 Dateien |
| **Centron.WPF.UI** | `src/centron/Centron.WPF.UI` | Windows-Fachclient | 3 657 Modul-, 688 Service-, 94 Prozess-Dateien |
| **Centron.WPF.UI.Extension** | `src/centron/` | Client-Erweiterungen | 34 Actions, 29 Module |
| **Centron.Controls / .Preview** | `src/shared/` | Wiederverwendbare Oberflächenbausteine | 75 PositionGrid, 69 PasswordManager, 58 MyDay u. a. |
| **CentronNexus / .Host** | `src/nexus/` | Blazor-Webanwendung („c-entron Web") | 136 Shared-, 94 ServiceBoard-Dateien; 491 Razor-Komponenten |
| **CentronNexus.OutlookAddIn** | `src/nexus/` | Outlook-Erweiterung | 22 Model-Dateien |
| **APIs** | `src/apis/` | Fremdsystemanbindungen: EbInterface, GLS, Shipcloud, COP, EGIS, finAPI, Icecat, ITscope | 56 FinAPI-, 23 Shipcloud-Dateien |
| **Deployment / Docker / CI** | `deployment/`, `docker/`, `azure/`, `.github/` | Installationspakete (WiX), Container, Pipelines | 4 Workflows, 6 Pipelines, 7 Vorlagen |
### 1.3 Fachliche Modulstruktur des Windows-Clients
Gemessen an der Zahl der C#/XAML-Dateien je Modulordner unter
`src/centron/Centron.WPF.UI/Modules`:
| Modul | Dateien | Modul | Dateien |
|---|---|---|---|
| Finances | 2 142 | Survey | 64 |
| Warehousing | 529 | Massenupdates | 48 |
| Administration | 327 | Sales | 42 |
| Helpdesk | 316 | Rma | 33 |
| DataExchange | 224 | PasswordManager | 29 |
| MyCentron | 211 | Production | 28 |
| Statistics | 141 | ProjectPriceImport | 19 |
| Purchasing | 136 | Calendar | 18 |
| Global | 111 | Reports | 10 |
| OnlineBanking | 88 | PayersAndCostCenter, TelekomDive, ProjectManagement | je 9 |
| ArtificialIntelligence | 68 | QM, PLM, Logistic | je 8 |
Die Verteilung zeigt, dass der Schwerpunkt des Systems eindeutig im Bereich **Finanzen/Belegwesen**
liegt (2 142 von 3 657 Dateien, rund 59 %). Die Analysetiefe wurde entsprechend gewichtet.
---
## 2. Abgedeckte Bereiche und Analysetiefe
Die Analyse folgte einer risikobasierten Priorisierung: Bereiche mit Auswirkung auf
**Sicherheit, Fakturierung/Abrechnung und Berechtigungen** wurden vertieft im Quelltext gelesen,
strukturelle und periphere Bereiche stichprobenhaft.
**Legende:** ● vertieft (zentrale Klassen vollständig oder in den maßgeblichen Abschnitten
gelesen) · ◐ stichprobenhaft (Signaturen, Schlüsselstellen, Struktur) · ○ nicht analysiert
| Bereich | Tiefe | Gelesene Schlüsselartefakte | Abgeleitete Anforderungen |
|---|---|---|---|
| Authentifizierung und Sitzungsverwaltung | ● | `Authenticator.cs`, `BasicAuthenticator.cs`, `AuthenticatorFactory.cs`, `TicketBL.cs`, `TicketAuthenticationHandler.cs`, `AuthenticateInterceptor.cs` | SyRS-001…010, SwRS-022…027 |
| Berechtigungen | ● | `AppRightsBL.cs` (vollständig), `UserRightsConst.cs` (Struktur + Belegblöcke), `WebAccountRightsConst.cs`, `CentronRights.md` | SyRS-011…013, SwRS-015…019 |
| Lizenzierung | ● | `LicenseManager.cs` (vollständig), `ApplicationKind.cs` (vollständig), `AccessTokenBL.cs` (Schlüsselstellen) | SyRS-007…009, SwRS-020, -021, -025 |
| Belegverarbeitung (Kern) | ● | `ReceiptBL.cs` (Speicherpfad, Rechteprüfung, Nummernvergabe, Zahlung, Protokollierung – ca. 900 von 13 000 Zeilen gezielt gelesen), `ReceiptBase.cs`, `ReceiptState.cs`, `ReceiptWebServiceBL.cs` (Schlüsselstellen) | SyRS-014…018, SwRS-004, -009, -012…015 |
| Nummernkreise | ● | `NumberGroupBL.cs` (vollständig), `NumberGroupEnum.cs` (vollständig) | SyRS-015, SwRS-010, -011 |
| Steuer- und Preisfindung | ● | `TaxBL.cs` (vollständig), `ReceiptItemPriceBL.cs` (Preisfindungskaskade) | SyRS-020, -021, SwRS-028, -029 |
| Lagerbuchung | ● | `ReceiptArticleBookingBL.cs` (Buchungspfad) | SyRS-019, SwRS-030, -031 |
| Helpdesk | ● | `HelpdeskBL.cs` (Speicher- und Rechtepfad), `HelpdeskCompact.cs` (vollständig) | SyRS-035, -036, SwRS-043, -044 |
| Verträge und automatische Abrechnung | ◐ | `AutomaticFacturaBL.Contracts.cs` (Selektions- und Markierungslogik, Methodenverzeichnis), `contracts-backend.md` | StRS-007, SyRS-022, SwRS-032 |
| Mahnwesen | ◐ | `DunningBL.cs` (Aggregation, Filter, Mahnstopp) | StRS-013, SyRS-037, SwRS-033 |
| E-Rechnung (ZUGFeRD/XRechnung) | ◐ | `InvoiceZugferdBL.cs` (Formatabbildung, Guideline-IDs), `ZugferdKind.cs` (vollständig) | StRS-011, SyRS-023, SwRS-045 |
| EDI | ◐ | Dateistruktur `SupplierEdiBL.*`, `edi-architecture.md` | StRS-014, SyRS-024, SwRS-046 |
| DSGVO / Datenschutz | ◐ | `DataSecurityBL.cs` (Methodenverzeichnis, Löschpfade, Konstanten) | StRS-016, SyRS-038, SwRS-047 |
| Hintergrunddienste und Betrieb | ● | `ManagedBackgroundService.cs` (vollständig), `DataQualityService.cs` (Kopf), Intervalle aller 33 Dienste | StRS-018, SyRS-025, -026, SwRS-034, -035 |
| Datenbankmigration | ● | `ScriptEngineBL.cs` (Kernalgorithmus), `ScriptMethod11803.cs` (vollständig), `create-scripts.md`, `database-conventions.md` | SyRS-027, SwRS-036, -037 |
| Konfiguration und Deployment | ● | `WebServiceConfigSerializer.cs`, `WebServiceConfig.xml`, `compose.yaml`, `appsettings.Production.json`, `Directory.Build.props`, `version.json` | SyRS-032, -033, -040, SwRS-039, -048, -049 |
| Webanwendung Nexus | ◐ | `AuthService.cs`, `PortAuthorization.cs`, Verzeichnis `Shared/Authorization`, Struktur der Razor-Komponenten | StRS-003, SyRS-034, SwRS-041, -042 |
| Windows-Fachclient | ◐ | `ModuleRegistration.cs` (Importliste, Registrierungsmuster), Modulverzeichnisstruktur | SwRS-040 |
| Buchhaltungsexport / DATEV | ◐ | `BookKeepingExportBL.cs` (Methodensignaturen) | StRS-012 |
| Online-Banking / finAPI | ◐ | `FinApiConstants.cs`, `RestClientBase.cs` (OAuth), Verzeichnisstruktur | StRS-020 |
| RMA | ◐ | `ReceiptBL.CheckCloseRMADeliverylistReceipt`, Nummernkreise, Objektarten | StRS-023 |
| Provision | ◐ | Entitätenliste, `FillReceiptWithProvision`, Hintergrunddienst | StRS-022 |
| Reporting / PDF-Ablage | ◐ | `ReceiptBL.AddReportPdf`, FastReport-Referenzen | StRS-021, SyRS-039 |
| Test- und CI-Infrastruktur | ◐ | Verzeichnis `tests/`, `.github/workflows/`, `azure/` | SwRS-050 |
| Statistik / Auswertung | ○ | – | – |
| Passwortmanager | ○ | – | – |
| Telefonie / TAPI / Communicator | ○ | – | – |
| Künstliche Intelligenz (Chat, Zusammenfassung) | ○ | – | – |
| MyDay / Zeitwirtschaft (eigenständig) | ○ | – | – |
| Produktion, PLM, QM, Logistik, Kommissionierung | ○ | – | – |
| Survey / Kampagnen / CRM-Projekte | ○ | – | – |
| Outlook-Add-In, Exchange-/Graph-Synchronisation | ○ | – | – |
| Fremd-APIs: GLS, Shipcloud, Icecat, ITscope, COP, docuFORM, EbInterface | ○ | – | – |
| Inventur, Seriennummern-/Barcodeverwaltung im Detail | ○ | – | – |
| Berichtswesen (Reportdefinitionen, ReportEngine) | ○ | – | – |
---
## 3. Ergebnis des Konsistenzchecks
Der Check wurde maschinell über alle drei Spezifikationsdateien ausgeführt (Extraktion aller
`ID:`-Zeilen, aller `Tracelinks:`- und `Konsolidierung:`-Referenzen sowie aller Belegmarkierungen).
| Prüfpunkt | Ergebnis |
|---|---|
| Anzahl Anforderungen gesamt | **119** (StRS 25, SyRS 43, SwRS 51) |
| Doppelte oder mehrfach vergebene IDs | **keine** |
| Anforderungen ohne Beleg | **keine** – jede der 119 Anforderungen führt mindestens einen Beleg |
| Anforderungen ohne `PRIMÄR`-Beleg | **keine** – jede der 119 Anforderungen führt mindestens einen `PRIMÄR`-Beleg |
| Tracelinks auf nicht existierende IDs | **keine** |
| SwRS-Anforderungen ohne Verweis auf eine SyRS-Anforderung | **keine** |
| SyRS-Anforderungen ohne Verweis auf eine StRS-Anforderung | **keine** |
### 3.1 Belegverteilung
| Ebene | Anforderungen | `PRIMÄR` | `SEKUNDÄR` | `KONTEXT` | Anteil `PRIMÄR` |
|---|---|---|---|---|---|
| StRS | 25 | 66 | 16 | 15 | 68,0 % |
| SyRS | 43 | 99 | 18 | 18 | 73,3 % |
| SwRS | 51 | 106 | 3 | 37 | 72,6 % |
| **Gesamt** | **119** | **271** | **37** | **70** | **71,7 %** |
Die risikobasierte Priorisierung wurde eingehalten: Alle Anforderungen zu Sicherheitsregeln
(SyRS-001…013, -029…034, SwRS-015…027, -039, -041, -042, -047), zur Abrechnungs- und
Fakturierungslogik (SyRS-014…023, -037, SwRS-028…033, -045) und zu Berechtigungen führen
mindestens einen `PRIMÄR`-Beleg. Keine Anforderung dieser Kategorien musste als `[HYPOTHESE]`
gekennzeichnet werden.
### 3.2 Weitere Kennzahlen
| Merkmal | Anzahl |
|---|---|
| Anforderungen mit `Status: … Workaround` (historischer Sonderfall / bekannte Altlast) | 29 |
| Anforderungen mit `[HYPOTHESE]`-markierter Teilaussage | 7 |
| Dokumentierte Konsolidierungskandidaten (Feld `Konsolidierung`) | 30 Einzelvermerke, verdichtet zu **19 Kandidaten** (K-01…K-19 in `Traceability.md`) |
| Hypothesen mit offener Frage (`Hypothesen.md`) | 12 |
---
## 4. Widersprüche zwischen Artefakten
Die Entwicklerdokumentation unter `docs/` wurde durchgängig als `KONTEXT` klassifiziert. Der
Grund ist ein nachweisbarer inhaltlicher Widerspruch zum Code:
| # | Widerspruch | Dokumentation | Code | Bewertung |
|---|---|---|---|---|
| W-01 | Belegzustandsmodell | `docs/reference/receipts/receipts-backend-architecture.md:284-290` nennt vier Zustände: „Draft – Released – Processed – Cancelled" | `ReceiptState` definiert drei Zustände: `Active` (offen), `Completed` (abgeschlossen), `Canceled` (storniert) | Code maßgeblich; siehe HYP-009 |
| W-02 | Verbindlichkeit der Schichtenarchitektur | `docs/getting-started/general-structure.md:3` räumt selbst ein: „there are tons of places where this general structure does not apply" | – | Die Sollarchitektur ist nicht flächendeckend umgesetzt; für die Migration ist von Abweichungen auszugehen |
| W-03 | Zentraler Rechtekonstantenkatalog | `docs/guides/development/check-userrights.md:5-6`: „Always use these constants instead of the id itself." | `ApplicationKind.cs:56-62` dupliziert vier Rechte-IDs als lokale Konstanten mit dem Kommentar „// Taken from UserRightsConst"; `AppRightsBL.GetAssignableAdminRightI3Ds()` führt 34 Zahlliterale | Regel wird im Bestand verletzt |
| W-04 | Lizenzkatalog als Wahrheitsquelle | `docs/reference/security/licensing-system.md:32-35`: „The single source of truth … is the license-server. We **try** to keep the `LicenseGuids.cs` file in sync" | `LicenseGuids.cs` ist eine manuell gepflegte Kopie | Der Katalog kann vom Lizenzserver abweichen |
---
## 5. Bekannte Lücken
### 5.1 Lücken in der Traceability
Drei StRS-Anforderungen besitzen keine korrespondierende SwRS-Anforderung, weil die zugehörige
Implementierung nur oberflächlich analysiert wurde:
| StRS | Thema | Fehlende SwRS-Ebene | Erforderlicher Nachschlag |
|---|---|---|---|
| StRS-021 | Belegdruck und PDF-Ablage | Reportengine, Reportdefinitionen, Dateinamensvariablen | `ReportDataBL` (92 KB), `PdfExportFilenameReplacementBL`, `Centron.Controls/Reports` (50 Dateien) |
| StRS-022 | Provisionsermittlung | Berechnungsalgorithmus je Schema und Stufe | `ReceiptProvisionBL` (45 KB) |
| — (SyRS-043) | Telemetrie | Konkrete Nutzdaten und Abschaltbarkeit | `TelemetryAggregator`, `HttpTelemetryUploadClient` |
### 5.2 Nicht verfügbare Artefaktklassen
| Fehlendes Artefakt | Auswirkung |
|---|---|
| **Datenbankschema-Abzug** (Tabellen, Spalten, Typen, Constraints, Indizes) | Das Datenmodell konnte nur indirekt über Entitäten, Mappings, Migrationsskripte und die Entwicklerdokumentation rekonstruiert werden. Dies ist die Hauptursache für die verbliebenen `KONTEXT`-Belege im Datenmodellbereich (siehe HYP-012). |
| **Ticketsystem / Anforderungsdokumente** | Commit-Messages verweisen systematisch auf Ticketnummern (z. B. „Ticket 168496", „Ticket 160276", „Ticket 124919"), die Tickets selbst liegen nicht vor. Fachliche Begründungen von Sonderfällen bleiben daher unbelegt. |
| **Release Notes / Migrationsnotizen** | Nicht im Arbeitsverzeichnis vorhanden. Die Versionshistorie ist nur über `version.json`, die Git-Historie (52 135 Commits seit 2014) und die `ApplicationVersion`-Angaben der 764 Migrationsskripte rekonstruierbar. |
| **Report- und Formulardefinitionen** | FastReport-Definitionen liegen nicht als lesbare Dateien im Repository; Belegdruckbilder konnten nicht ausgewertet werden. |
| **Betriebs- und Lastdaten** | Keine Aussagen zu realen Antwortzeiten, Datenvolumina oder Nutzerzahlen möglich; die nicht-funktionalen Anforderungen zur Performanz beschränken sich daher auf im Code verankerte Größen (Intervalle, Blockgrößen, Cache-Zeiten). |
### 5.3 Bewusst nicht erfasste Bereiche
Die in Abschnitt 2 mit ○ markierten Bereiche wurden nicht analysiert. Der größte
Einzelblock ist `Statistics` (141 UI-Dateien, `ContractEvaluationBL` 87 KB, `MspCollectorsBL`
70 KB, `Centron.BL/Statistics` 16 Dateien); der zweitgrößte der Passwortmanager
(`Centron.Controls/PasswordManager` 69 Dateien, `Modules/PasswordManager` 29 Dateien,
eigene Lizenz `LicenseGuids.PasswordManager`, eigener Rechtebereich).
---
## 6. Selbstbewertung
### 6.1 Vollständigkeit der Analyse
**Vollständig analysiert** (zentrale Klassen in den maßgeblichen Teilen gelesen, Aussagen
durchgängig `PRIMÄR` belegt):
Authentifizierung, Sitzungsverwaltung, Berechtigungen, Lizenzierung, Nummernkreise,
Steuersatzermittlung, Belegzustands- und Versionsmodell, Belegrechteprüfung, Lagerbuchung,
Helpdesk-Rechte- und Speicherpfad, Hintergrunddienst-Rahmenwerk, Datenbankmigration,
Betriebskonfiguration und Bauvorgaben.
**Stichprobenhaft analysiert** (Struktur, Signaturen und Schlüsselstellen gelesen; die
Anforderungen beschreiben das Verfahren korrekt, aber nicht erschöpfend):
Vertragsabrechnung, Mahnwesen, E-Rechnung, EDI, DSGVO, Nexus-Webanwendung, Windows-Fachclient,
Buchhaltungsexport, Online-Banking, RMA, Provision, Reporting, Testinfrastruktur.
**Nicht analysiert:** siehe Abschnitt 2 (○-Zeilen) und HYP-001.
Belastbare Schätzung des Abdeckungsgrads: Die 119 Anforderungen decken die
**architektur- und sicherheitsprägenden Mechanismen weitgehend vollständig** ab, die
**fachliche Breite** jedoch nur zu einem geschätzten Drittel. Insbesondere fehlen die
Auswertungs- und Statistiklogik sowie mehrere eigenständige Fachmodule.
### 6.2 Stellen mit dünner Beleglage
Der Anteil von `PRIMÄR`-Belegen liegt insgesamt bei 71,7 %. Die folgenden 20 Anforderungen
stützen sich auf genau einen `PRIMÄR`-Beleg und sollten in einer Folge-Iteration verstärkt werden:
| Anforderung | Beleglage | Grund |
|---|---|---|
| StRS-012 (Buchhaltungsübergabe) | 1 × PRIMÄR, 1 × SEKUNDÄR | `BookKeepingExportBL` (81 KB) nur über Methodensignaturen erfasst |
| SwRS-005 (Objekttypschlüssel) | 1 × PRIMÄR, 3 × KONTEXT | Die Aussage stützt sich stark auf Quelltextkommentare |
| SwRS-007 (Versionstabellen) | 1 × PRIMÄR, 1 × KONTEXT | Nur ein Migrationsskript als Nachweis; kein Schemaabzug (HYP-012) |
| SwRS-002 (Doppelimplementierung) | 1 × PRIMÄR, 1 × KONTEXT | Die Verbindlichkeit stammt aus der Dokumentation (HYP-006) |
| SwRS-035 (Datenqualitätsaufgaben) | 1 × PRIMÄR, 1 × KONTEXT | Aufgaben 4–9 nur dokumentiert (HYP-008) |
| SyRS-010, -021, -026, -028, -033, -039; SwRS-011, -012, -013, -020, -025, -031, -037, -043; SyRS-005 | je 1 × PRIMÄR | ausreichend für die Kernaussage, aber ohne Bestätigung durch einen zweiten Fundort |
Bereiche mit auffällig hohem `KONTEXT`-Anteil: **Datenmodell und Schemastruktur**
(SwRS-005, -006, -007, -008) sowie **EDI** (SwRS-046, SyRS-024). In beiden Fällen ist die
Ursache dieselbe: Es fehlen maschinenlesbare Strukturartefakte (Schemaabzug, EDI-Beispieldateien).
Der `SEKUNDÄR`-Anteil ist auf SwRS-Ebene mit 3 Belegen (2,1 %) auffällig niedrig. Das ist
plausibel, weil UI-Texte und Konfigurationsschalter fachliche Aussagen auf StRS-/SyRS-Ebene
tragen, während die SwRS-Ebene definitionsgemäß Codeeigenschaften beschreibt.
### 6.3 Migrationsrelevante Befunde (Priorisierung für die Validierung)
Die 29 als `Workaround` gekennzeichneten Anforderungen sind die Arbeitsliste für die
Fachvalidierung. Die aus meiner Sicht kritischsten sieben:
| Rang | Befund | Anforderung | Warum kritisch |
|---|---|---|---|
| 1 | **Kennwörter als ungesalzenes SHA-1** – im Quelltext selbst als `// TODO the password should be salted!!!` markiert | SyRS-004, SwRS-024 | Identische Kennwörter erzeugen identische Hashwerte; für ein SaaS-Zielsystem nicht tragbar. Die Migration erfordert einen Neuvergabe- oder Rehash-bei-Anmeldung-Pfad. |
| 2 | **DSGVO-Löschung unvollständig** – `DoDeleteCustomer`, `DoDeleteSupplier`, `DoDeleteAccount` werfen `NotImplementedException` | StRS-016, SyRS-038, SwRS-047 | Compliance-Lücke mit rechtlicher Wirkung; die vorgesehenen SQL-Anweisungen liegen nur auskommentiert vor. |
| 3 | **Zwei Persistenzpfade für Belege** (NHibernate-Entität + Legacy-Repository auf Alttabellen) | SwRS-006, SwRS-008 | Laut Architekturdokumentation eine bekannte Fehlerquelle („value may load correctly from the view but will not be persisted on save"). Für die Neuimplementierung ist ein bereinigtes Schema Voraussetzung. |
| 4 | **Klartextpfad für Verbindungsgeheimnisse** (`DatabaseConnectionStringPlain`) und mitgelieferte Beispielschlüssel (`SecretKey` identisch in zwei Auslieferungsdateien) | SyRS-032, SwRS-039 | Betriebsrisiko; zusätzlich sind Zertifikatspasswort und Signaturschlüssel gar nicht verschlüsselt. |
| 5 | **Doppelbuchungsschutz als Symptombehandlung** – Kommentar zu Ticket 124919: „We cant reproduce this issue" | SwRS-031 | Eine ungeklärte Bestandsverfälschung darf nicht in ein Zielsystem übernommen werden; die Ursache ist vor der Migration zu klären. |
| 6 | **Sicherheit ist Opt-in** – eine Dienstmethode ohne `AuthenticateAttribute` ist unauthentifiziert erreichbar | SwRS-027 | Im Zielsystem ist „sicher per Voreinstellung" (Opt-out) zu wählen. |
| 7 | **`EnableUnsafeBinaryFormatterSerialization` und Unterdrückung von NuGet-Schwachstellenwarnungen** | SwRS-049 | Bewusst akzeptierte Risiken, die eine Neuimplementierung nicht fortschreiben sollte. |
### 6.4 Empfehlungen für eine Folge-Iteration
Nach Wirkung geordnet:
1. **Datenbankschema-Abzug bereitstellen und einlesen.** Dies ist die wirkungsvollste
Einzelmaßnahme: Sie ersetzt den Großteil der `KONTEXT`-Belege im Datenmodellbereich durch
`PRIMÄR`-Belege und klärt HYP-012 vollständig. Ohne Schema bleibt die Datenspezifikation für
eine Neuimplementierung unvollständig.
2. **Fachliche Breite nachziehen.** Schwerpunkte: `Statistics` (Auswertungslogik,
Vertragsbewertung, MSP-Collector), Passwortmanager, MyDay/Zeitwirtschaft, Kommissionierung
und Inventur. Diese Bereiche tragen eigenständige Geschäftsregeln, die bisher fehlen.
3. **`ReceiptBL` vollständig erschließen.** Die Klasse umfasst 609 KB (über 13 000 Zeilen);
in diesem Lauf wurden gezielt rund 900 Zeilen gelesen. Alle nicht gelesenen Abschnitte sind
potenzielle Quellen weiterer Geschäftsregeln – insbesondere Belegweiterführung, Kopieren,
Frachtartikel, Kundenrabattpositionen, Excel-Export und Mailversand.
4. **Positionsebene der Belege erfassen.** `ReceiptItemBL` (225 KB) und `ReceiptItemTimerBL`
(104 KB) wurden nicht gelesen. Positionslogik (Mengen, Preise, Rabatte, Verknüpfung mit
Zeiterfassung) ist für ein Zielsystem mindestens so wichtig wie die Kopflogik.
5. **Rechte vollständig katalogisieren.** `UserRightsConst.cs` enthält über 60 verschachtelte
Klassen; in diesem Lauf wurden die Belegblöcke und einzelne Bereiche gelesen. Ein
vollständiger, maschinell extrahierter Rechtekatalog mit Zuordnung zu den prüfenden
Codestellen wäre für das Zielsystem unmittelbar verwertbar.
6. **Offene Fragen HYP-004, HYP-010, HYP-011 klären.** Alle drei betreffen Integrität
(fakturierte Zeiten, Wirksamkeit des Rechteentzugs, Datenverlust bei Nebenläufigkeit) und sind
mit begrenztem Leseaufwand entscheidbar.
7. **Testbestand als Anforderungsquelle nutzen.** Die 378 Testdateien – insbesondere
`Centron.Tests.EndToEnd` und `Centron.Tests.Integration` – enthalten ausführbare
Sollaussagen. Sie sind eine bisher ungenutzte `PRIMÄR`-Belegquelle und eignen sich
besonders zur Bestätigung von Geschäftsregeln, die aus Implementierungscode nur
interpretativ ableitbar sind.
### 6.5 Einschränkungen dieses Laufs
- Die Analyse erfolgte **rein statisch**. Kein Programmteil wurde ausgeführt, keine Datenbank
angebunden, kein Test ausgeführt. Alle Prüfideen sind Vorschläge, keine Nachweise.
- Die Codebasis wurde **ausschließlich gelesen** und nicht verändert; dies wurde durch die
Beschränkung auf lesende Werkzeuge sichergestellt.
- Textsuchen über die gesamte Codebasis liefen mehrfach in eine Zeitüberschreitung und mussten
auf Teilverzeichnisse eingegrenzt werden. Es ist daher möglich, dass Fundstellen außerhalb der
durchsuchten Verzeichnisse übersehen wurden. Wo eine Aussage auf Vollständigkeit angewiesen
ist (z. B. „an sieben Stellen kopiert"), bezieht sie sich auf das jeweils genannte
Suchverzeichnis.
- Angaben zu Zeilennummern beziehen sich auf den Stand des Commits `79c1142f48`
(25.08.2026, „Versuchsbasis: KI-Assistenz-Konfigurationen entfernt").
@@ -0,0 +1,119 @@
# Glossar
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Zweck:** Definition aller Domänenbegriffe, die in `StRS.md`, `SyRS.md` und `SwRS.md` verwendet
werden. Jeder Begriff nennt die technische Entsprechung in der Codebasis, damit die Zuordnung
zwischen fachlicher Aussage und Artefakt eindeutig bleibt.
Spalte **Beleg** verweist auf das Artefakt, aus dem die Definition abgeleitet ist.
---
## 1. Kernbegriffe des Belegwesens
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Beleg** | Kaufmännisches Dokument mit Kopfdaten und Positionen, das einen Geschäftsvorfall zwischen dem Betreiber und einem Kunden oder Lieferanten dokumentiert. Kundenbelege und Lieferantenbelege werden unterschieden. | `ReceiptBase` (abstrakt), `IReceiptBase` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9` |
| **Belegart** | Fachliche Klasse eines Belegs (Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag, Anfrage, Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift). | `CentronObjectKindNumeric` mit `IsCustomerReceipt()` / `IsSupplierReceipt()` | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:268-301` |
| **Belegkopf** | Kopfdatensatz eines Belegs (Nummer, Datum, Empfänger, Adressen, Währung, Zustand). Physisch in Tabellen mit der Endung `Kopf`. | `AngKopf`, `AufKopf`, `LiefKopf`, `RechKopf`, `VertragKopf`, `GutKopf`, `AbholKopf` | `src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:78-137` |
| **Belegposition** | Einzelne Zeile eines Belegs (Artikel, Text, Rabatt, Fracht). Physisch in Tabellen mit der Endung `Pos`. | `AngPos`, `AufPos`, `LiefPos`, `RechPos`, `VertragPos`, `GutPos`, `AbholPos`; Entität `ReceiptItemBase` | `docs/reference/receipts/receipts-backend-architecture.md:74-82` |
| **Positionsart** | Typ einer Belegposition; bestimmt insbesondere, ob eine Lagerbuchung erfolgt. | `ReceiptItemKind` (u. a. `Article`, `CustomerDiscount`, `SupplierFreightNoSplitArticle`, `SupplierInsuranceNoSplitArticle`) | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:174-177` |
| **Belegzustand** | Fachlicher Bearbeitungsstand eines Belegs: *offen*, *abgeschlossen*, *storniert*. | `ReceiptState.Active = 1`, `Completed = 2`, `Canceled = 3` | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-14` |
| **Belegversion** | Fortlaufende Nummer einer inhaltlichen Belegfassung. Jede neue Version archiviert den Vorzustand vollständig. | `ReceiptBase.Version`, Versionstabellen `*KopfVersions` / `*PosVersions` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578` |
| **Belegvorlage** | Beleg, der nicht Teil des produktiven Geschäftsvorfalls ist, sondern als Muster dient. Erkennbar an negativer Belegnummer und Zuordnung zum konfigurierten Vorlagenkunden. | `ReceiptBase.IsTemplate => Number < 0`, `ReceiptTemplateBL` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:65` |
| **Belegweiterführung** | Erzeugung eines Folgebelegs aus einem oder mehreren Vorgängerbelegen unter Übernahme von Positionen (z. B. Auftrag → Lieferschein). | `ReceiptWebServiceBL.ForwardReceipt`, `CanForwardReceiptsInto` | `…/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2315-2336` |
| **Verarbeitete Menge** | Anteil der Positionsmenge, der bereits in einen Folgebeleg übernommen wurde. Steuert gemeinsam mit der Gesamtmenge die Lagerbuchung. | `IReceiptItemBase.QuantityProcessed`, `QuantityComplete` | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:191-193` |
| **Belegempfänger** | Adressblock eines Belegs. Es werden bis zu vier Empfänger geführt: Standard-, Rechnungs-, Liefer- und Lizenznehmeradresse. | `ReceiptReceiver`, `ReceiptReceiverInvoice`, `ReceiptReceiverDelivery`, `ReceiptReceiverLicense` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:58-61` |
| **Nummernkreis** | Konfigurierbarer Zähler je Belegart, Mandant und Filiale mit Startwert, Schrittweite und Wertebereich. | Entität `NumberGroup`, Aufzählung `NumberGroupEnum` (31 Werte) | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:50-134` |
| **Nebenläufigkeitskennzeichen** | GUID, die bei jeder Belegänderung neu gesetzt wird und beim Schreiben gegen den vom Client mitgeführten Wert geprüft wird (optimistische Sperre). | `ReceiptBase.ConcurrencyControlGuid`, Datenbankspalte `GUI3D` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4939-4940` |
| **Belegsperre** | Pessimistische, benutzerbezogene Sperre eines Belegs während der Bearbeitung. | `TryLockReceipt`, `UnLockReceipt` über `SpecificLogics` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3087-3093, 3166-3174` |
## 2. Stammdaten und Organisation
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Mandant** | Rechtliche Einheit, für die Belege geführt werden. Genau ein Mandant ist als Standard gekennzeichnet. | Entität `Mandator` (`Default == 1`), `CentronObjectKindNumeric.Company = 53` | `src/backend/Centron.BL/Administration/Company/MandatorBL.cs:19-22` |
| **Filiale** | Organisatorische Untereinheit eines Mandanten mit eigenen Nummernkreisen und eigenem Sichtbarkeitsbereich. | `BranchI3D`, `BranchBL`, `CentronObjectKindNumeric.Branch = 124` | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152` |
| **Standardfiliale** | Zustand „keine Filiale zugeordnet". Wird technisch sowohl als `NULL` als auch als `0` dargestellt; beide gelten als gleichwertig. | `BranchBL.IsBranchEqual`, Prüfung in `CanUserCreateReceiptsInBranch` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10258-10267` |
| **Kunde** | Geschäftspartner auf der Absatzseite. Es existieren zwei Datenstrukturen: die Alttabelle `Kunden` und die neuere `Account`-Struktur. | `CentronObjectKindNumeric.Customer = 12`, `CustomerClass = 5000012`, `Account = 7600071` | `…/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2372-2392` |
| **Lieferant / Kreditor** | Geschäftspartner auf der Beschaffungsseite. | Tabelle `Kreditor`, `CentronObjectKindNumeric.Creditor = 20` | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:124-131` |
| **Artikel** | Verkaufs- oder Beschaffungsgegenstand mit Artikelcode, Warengruppe, Steuersatz und Preisen. | Entitäten `Article`, `ArticleLight`, Tabelle `Artik`, `CentronObjectKindNumeric.Article = 9` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:246-275` |
| **Warengruppe / Sekundär-Warengruppe** | Zweistufige Klassifikation von Artikeln; dient unter anderem als Fallback für die Steuersatzermittlung. | `MaterialGroup = 70`, `SecondaryMaterialGroup = 136`, `MaterialGroupBL` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:257-273` |
| **Lager** | Bestandsführender Ort. Es wird zwischen Hauptlager (kein bzw. Kennung −1) und Nebenlagern unterschieden. | Entität `Stock`, `StockBL`, `SecondStockArticleBL` | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:136` |
| **Mitarbeiter** | Person im Unternehmen des Betreibers; Grundlage für Benutzerkonto, Filialzuordnung, Zeiterfassung und Provision. | `EmployeeCompact`, Tabelle `Personal`, `CentronObjectKindNumeric.EmployeeClass = 215` | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:206` |
## 3. Benutzer, Rechte und Lizenzen
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Benutzer (interner Benutzer)** | Anmeldekonto eines Mitarbeiters am ERP-System. | Entität `AppUser`, Tabelle `Sichbenu` | `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:49-50` |
| **Web-Account** | Anmeldekonto eines Endkunden für Selbstbedienungsfunktionen; besitzt ein eigenes, disjunktes Rechtemodell. | Entität `WebAccount`, Tabellen `WebAccounts`, `WebAccountsRights` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:679-691` |
| **Rechtegruppe** | Bündel von Rechten. Rechte werden ausschließlich über Gruppen an Benutzer vergeben. | Entität `AppGroup`, Tabelle `Sichgrup` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48` |
| **Recht** | Einzelne, numerisch identifizierte Berechtigung für eine fachliche Funktion. | Entität `AppRight`, Tabelle `Sichtrus` (Zuordnung Gruppe→Recht), Konstantenkatalog `UserRightsConst` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:653-656` |
| **Einschränkendes Recht** | Recht mit umgekehrter Wirkung: Sein *Besitz* verkleinert den Zugriffsbereich (z. B. „nur eigene", „nur eigene Filiale"). | z. B. `SHOW_OFFERS_ONLY_OWN`, `SHOW_HELPDESK_ONLY_OWN_BRANCH` | `CentronRights.md:9-17`; `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10284-10292` |
| **Ausschließendes Recht** | Recht, dessen Besitz die Anmeldung an einer bestimmten Anwendung *verhindert*. | `ApplicationKind.DisallowingRight`, z. B. `RIGHT_DISALLOW_SERVICEBOARD_LOGIN` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45, 60` |
| **Anwendung (ApplicationKind)** | Am Anwendungsserver anmeldefähiges Produkt mit eigener Lizenz-GUID, Ticketlebensdauer und Lizenzzählweise. | `ApplicationKind` (43 registrierte Instanzen) | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| **Lizenz** | GUID-identifiziertes Nutzungsrecht mit optionaler Anzahl, Ablaufdatum und maximaler Programmversion. | `LicenseGuids`, `LicenseManager.CheckLicense`, `GetLicenseCount` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302` |
| **Lizenzzählweise** | Regel, ob eine Lizenz je Benutzer oder je Benutzer und Gerät verbraucht wird. | `LicenseUsageKind.PerUser`, `PerUserAndPerMachine` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:173-177` |
| **Ticket (Sitzungsticket)** | Serverseitig geführter Sitzungsnachweis, gebunden an Anwendung, Benutzer bzw. Web-Account und Gerät, mit Ablaufzeitpunkt. **Nicht zu verwechseln mit dem Helpdesk-Ticket.** | Entität `Ticket` (Namensraum `Centron.Data.Entities.Ticketing`), `TicketBL`, `TicketRepository` | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:61-94` |
| **Access Token** | Persönlicher, lizenzpflichtiger Langzeittoken für Maschinen-zu-Maschinen-Zugriffe; nur der SHA-256-Hash wird gespeichert. | Entität `AccessToken`, `AccessTokenBL`, `AccessTokenLogBL` | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:154-186, 477-483` |
## 4. Vertrieb, Preise und Steuern
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Sonderpreis (Kunde)** | Kundenindividuelle Preiskondition mit fünf Änderungsarten (Aufschlag auf EK, Abschlag auf UVP, Festpreis, Abschlag auf VK, Abschlag auf Listenpreis). | `CustomerSpecialPrice`, `SpecialPriceKind` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:232-259` |
| **Vertragssonderpreis** | Vertragsbezogene Preiskondition, kombinierbar aus fünf Preisbasen und zwei Änderungsmodi (absolut/prozentual). Die Werte sind vorzeichenverkehrt hinterlegt. | `ContractSpecialPrice`, `ContractSpecialPriceKind`, `ContractSpecialPriceChangeKind` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-227` |
| **Staffelpreis** | Mengenabhängiger Preis, der nachrangig zu Sonderpreisen greift. | `ArticleVolumePrices`, `ArticleVolumePricesBL` | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:261-266` |
| **Mehrwertsteuersatz** | Steuersatz mit Ablaufdatum und Verweis auf den Folgesatz; bildet eine zeitliche Kette. | Entität `ValueAddedTax` mit `NextTaxRate`, `ExpirationDate`; `TaxBL` | `src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237` |
| **Provisionsschema** | Regelwerk zur Ermittlung von Vertriebsprovisionen, zuordenbar zu Kunden und Mitarbeitern, mit Zielvorgaben und Stufen. | `ReceiptProvisionSchema`, `…SchemaItem`, `…SchemaCustomerAssignment`, `…EmployeeGoal`, `…EmployeeLevel` | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs` |
| **Mahnstufe** | Eskalationsstufe einer überfälligen Forderung; vier Ausprägungen (keine, 1, 2, 3). | `DunningLevel.None`, `Level1`, `Level2`, `Level3` | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-210` |
| **Mahnstopp** | Befristete Aussetzung des Mahnverfahrens, setzbar je Kunde oder je Beleg, mit Begründung. | `DunningStop`, `DunningStopBegin`, `DunningStopEnd`, `DunningInfo` | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431` |
## 5. Verträge und Service
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **Vertrag** | Belegart für wiederkehrende Leistungen mit Abrechnungsintervall, Laufzeit und optionaler automatischer Verlängerung. | `ReceiptContract`, `ContractClass = 22`, Tabellen `VertragKopf`/`VertragPos` | `docs/reference/receipts/contracts-backend.md:11-95` |
| **Abrechnungsintervall** | Zyklus, in dem aus einem Vertrag Rechnungen erzeugt werden (Art × Dauer, z. B. Monat × 3 = quartalsweise). | `BillingIntervalKind`, `BillingIntervalDuration` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:836` |
| **Kalkulationsart (Vertrag)** | Steuert, ob ein Vertrag automatisch, nach Bedarf oder manuell abgerechnet wird. | `ContractCalculationKind.Auto`, `Need`; `ContractNeedCalcKind.Dynamic` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:829-830, 882-884` |
| **Vertragszusatzart** | Kennzeichnet, ob ein Vertrag einfach, klickbasiert (Geräte­zähler) oder kontingentbasiert ist. | `ContractExtraKind.Easy`, `ClickDevice`, `Contingent` | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:837-840` |
| **Kontingent** | Vorab vereinbartes Leistungsvolumen (Stunden oder Betrag), das über die Vertragslaufzeit verbraucht wird. | `IReceiptWithContingent` mit `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentLimitValue` u. a. | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10318-10369` |
| **Stammblatt** | Liste von Geräten oder Objekten, die einem Vertrag zugeordnet sind (Grundlage für Klickabrechnung). | `MasterDataList`, `MasterDataListItem`, `MasterDataListClass = 25` | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:59, 314` |
| **Helpdesk-Ticket** | Serviceanfrage mit Nummer, Kunde, Status, Priorität, Typ, bis zu drei Kategorieebenen, Verantwortlichem und Fälligkeit. | Entität `Helpdesk` / `HelpdeskCompact`, Tabelle `hlpdsk_requests`, `HelpdeskClass = 10` | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:12-120` |
| **Ticketstatus** | Frei konfigurierbarer Bearbeitungsstand eines Helpdesk-Tickets. Ein Statuswert ist in den Einstellungen als „geschlossen" ausgezeichnet. | `HelpdeskStateI3D`, `HelpdeskSettingsBL.GetClosedHelpdeskState()` | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433` |
| **Zeiterfassung (Helpdeskzeit)** | Erfasste Arbeitszeit zu einem Ticket, unterschieden nach Berechenbarkeit, Planungsstatus und Abrechnungszustand. | `HelpdeskTimer`, `HelpdeskTimerBillingState`, `HelpdeskTimerTypes` | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90` |
| **RMA** | Rücksendungs- und Reparaturvorgang (Return Merchandise Authorization), kunden- und lieferantenseitig getrennt geführt. | `RmaBL`, `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180` |
## 6. Schnittstellen und Datenaustausch
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **EDI** | Elektronischer Geschäftsdatenaustausch mit Distributoren (Auftragsbestätigung, Lieferavis, Rechnung). | `SupplierEdiBL` mit lieferantenspezifischen Partial Classes, `EDILogBL` | `src/backend/Centron.BL/EDI/SupplierEDI/` |
| **EDI-Format** | Datenformat eines Distributors. Unterstützt werden OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron und ZUGFeRD. | `EdiDataType` | `docs/reference/edi/edi-architecture.md:177-188` |
| **ZUGFeRD / XRechnung** | Standards für strukturierte elektronische Rechnungen. ZUGFeRD bettet die XML-Rechnung in ein PDF/A-3 ein; XRechnung ist das rein strukturierte Format der öffentlichen Verwaltung. | `ZugferdKind` (6 Profilstufen), `InvoiceZugferdBL` | `src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:11-27` |
| **Guideline-ID** | Normkennung, die das verwendete E-Rechnungsprofil im XML ausweist (KoSIT-URN). | Zuordnung in `InvoiceZugferdBL` | `…/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289` |
| **Buchhaltungsexport** | Übergabe von Debitoren- und Kreditorenbuchungssätzen an die Finanzbuchhaltung, optional als DATEV-Online-Paket mit Belegbild. | `BookKeepingExportBL`, `GetDatevOnlinePackageForExport` | `…/DataExchange/BookKeeping/BookKeepingExportBL.cs:832, 1437, 1560` |
| **finAPI** | Bankenaggregator zur Abfrage von Kontoumsätzen; getrennte Sandbox- und Live-Endpunkte. | `Centron.APIs.FinAPI`, `FinApiClient` | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
## 7. Technische Querschnittsbegriffe
| Begriff | Definition | Technische Entsprechung | Beleg |
|---|---|---|---|
| **I3D** | Systemweite Bezeichnung für den technischen Primärschlüssel („ID 3develop"). Jede Tabelle besitzt eine Spalte `I3D` als `int IDENTITY(1,1)`. Fremdschlüsselspalten enden auf `I3D`. | Spalte `I3D`, Suffix `…I3D` | `docs/guides/database/database-conventions.md:12-36` |
| **Objektart (ObjectKind)** | Numerischer Diskriminator für polymorphe Referenzen nach dem Muster `ObjectI3D` + `ObjectKind`. In Altbeständen `AnlageI3D` + `AnlageArt`. | `CentronObjectKindNumeric` (über 230 Werte) | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:20-264` |
| **Ergebnisobjekt (`Result<T>`)** | Einheitlicher Rückgabetyp der Geschäftslogik mit Zustand, Meldung und maschinenlesbarem Fehlercode. | `Result`, `Result<T>`, `ResultStatus`, `DefaultMessageCodes` | `src/backend/Centron.Interfaces/BL/` |
| **BL-Logik / WS-Logik** | Doppelimplementierung einer Clientfunktion: `BL*Logic` greift direkt auf die Datenbank zu, `WS*Logic` ruft den Anwendungsserver. | `I{Modul}Logic`, `BL{Modul}Logic`, `WS{Modul}Logic`, `ClassContainer` | `docs/getting-started/general-structure.md:36-113` |
| **WebServiceBL** | Schicht, die Domänenentitäten in DTOs umwandelt und die Dienstfassade bedient. | `*WebServiceBL`-Klassen unter `Centron.BL/WebServices` | `src/backend/Centron.BL/WebServices/` (464 Dateien) |
| **SpecificLogic** | Belegartspezifische Implementierung, an die die generische Belegverarbeitung delegiert. | `OfferSpecificLogic`, `InvoiceSpecificLogic`, `ContractSpecificLogic` u. a.; Verteiler `SpecificLogics` | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7267, 10277` |
| **Legacy-Sicht** | Englisch benannte Datenbanksicht auf eine deutsch benannte Alttabelle; normalisiert Spaltennamen, Nullwerte und ungültige Datumswerte. | `Offers`, `Orders`, `DeliveryLists`, `Invoices`, `Contracts`, `CreditVouchers`, `PickupLists` | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs` |
| **Versionstabelle** | Strukturgleiche Kopie einer Belegtabelle zur Archivierung früherer Belegversionen. | `*KopfVersions`, `*PosVersions` mit `OriginalI3D` / `KopfVersionsI3D` | `docs/reference/receipts/receipts-backend-architecture.md:147-172` |
| **Migrationsskript** | Nummerierte, versionsgebundene und genau einmal ausführbare Schemaänderung. | `ScriptMethod<Nummer> : BaseScriptMethod`, Ausführungsstand in Tabelle `DBUpdate` | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177` |
| **Anwendungseinstellung** | Betreiberseitig konfigurierbarer Parameter. Es existieren zwei Systeme: Alttabelle `Stammdat` und aktuelle Tabelle `ApplicationSettings`. | `AppSettingsConst`, `ApplicationSettingID`, `AppSettingsBL`, `AppSettingsGroupBL` | `docs/guides/development/settings-management.md:5-31` |
| **Hintergrunddienst** | Zeitgesteuerter, unbeaufsichtigt laufender Verarbeitungsprozess im Anwendungsserver. | Ableitungen von `ManagedBackgroundService` (33 Dienste) | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:12-180` |
| **Interceptor** | Querschnittliche Vor- und Nachverarbeitung von Dienstaufrufen (Authentifizierung, Protokollierung, Fehlerbehandlung, Telemetrie) mit definierter Reihenfolge. | Castle-DynamicProxy-Interceptoren mit `Priority`, gesteuert über Attribute | `…/WcfBridge/Interception/Interceptors/` |
| **Nexus** | Blazor-basierte Webanwendung der Suite („c-entron Web"), enthält Service-Board, WebCart, WebOffer und Verwaltungsfunktionen. | Projekte `CentronNexus`, `CentronNexus.Host` | `README.md:1`, `docker/compose/compose.yaml:38-50` |
| **Service-Board** | Ticket- und Servicearbeitsplatz innerhalb von Nexus, auch als eigenständig lizenziertes Produkt geführt. | `CentronNexus/ServiceBoard/`, `ApplicationKind.ServiceBoard`, `ServiceBoardNext` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45, 53` |
| **WebCart** | Kundenshop innerhalb von Nexus; die verfügbaren Artikel stammen aus den Sonderpreisen des jeweiligen Kunden. | `CentronNexus/WebCart/`, `ApplicationKind.WebCart` | `README.md:31-36` |
| **Riversuite / DocuBoard** | Angrenzende Produktfamilie (Inventarisierung, Monitoring, Fernwartung), die sich am selben Anwendungsserver anmeldet. | `ApplicationKind.Riversuite*`, `LicenseGuids.Riversuite*` | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:34-44` |
| **c-entron Delphi** | Vorgängersystem, das dieselbe Datenbank und dieselben Lizenz-GUIDs nutzt. Seine Versionsnummern (9.3.x) werden bei der Lizenzprüfung gesondert behandelt. | `LicenseManager.TryFixCentronDelphiVersionNumber` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:304-330` |
@@ -0,0 +1,311 @@
# Hypothesen und offene Fragen
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Zweck:** Sammlung aller Aussagen, die aus den vorliegenden Artefakten **nicht** eindeutig
abgeleitet werden konnten, samt der jeweils fehlenden Information. Jede Hypothese ist an eine
konkrete offene Frage für die manuelle Validierung durch Fachexperten (Schritt 7 der
RRE-Methodenkette) gebunden.
**Lesart:** `Betroffene Anforderung` verweist auf die Stelle, an der die Teilaussage mit
`[HYPOTHESE]` markiert ist. `Beobachtung` nennt, was tatsächlich im Artefakt steht.
`Fehlende Information` benennt, was zur Bestätigung oder Widerlegung erhoben werden müsste.
---
## HYP-001 — Nicht analysierte Module
**Betroffene Anforderung:** keine einzelne; betrifft die Vollständigkeit der Spezifikation insgesamt.
**Beobachtung:** Die Codebasis umfasst 14 782 C#-, 1 233 XAML- und 491 Razor-Dateien in 44 Projekten.
In diesem Lauf wurden schwerpunktmäßig Beleg-, Rechte-, Lizenz-, Anmeldungs-, Vertrags-, Helpdesk-,
Lager-, Steuer-, EDI-, E-Rechnungs-, DSGVO-, Betriebs- und Migrationslogik analysiert. Ganze
Modulbereiche wurden nicht geöffnet, darunter: `Statistics` (141 UI-Dateien, `ContractEvaluationBL`
87 KB, `MspCollectorsBL` 70 KB), `Survey` (64 UI-Dateien), `Massenupdates` (48), `Production`,
`ProjectPriceImport`, `PLM`, `QM`, `TelekomDive`, `PayersAndCostCenter`, `ArtificialIntelligence`
(68 UI-Dateien, `Centron.BL/ArtificialIntelligence` 25 Dateien), `Centron.Controls/PasswordManager`
(69 Dateien), `Centron.Controls/MyDay` (58), `Centron.Controls/Telephony`/`Tapi`,
`CentronNexus.OutlookAddIn`, `Centron.Api.docuFORM`, `Centron.Api.Gls`, `Centron.Api.Shipcloud`,
`Centron.APIs.CopDataAccess`, `Centron.APIs.IcecatDataAccess`, `Centron.APIs.ITscopeDataAccess`.
**Aussage [HYPOTHESE]:** Die in dieser Spezifikation dokumentierten Architektur- und
Querschnittsmuster (Schichtung, `Result<T>`, Rechteprüfung über `UserRightsConst`, Nummernkreise,
Sitzungscache, `ManagedBackgroundService`) gelten auch für die nicht analysierten Module.
**Fehlende Information:** Stichprobenanalyse mindestens eines Moduls je nicht abgedecktem Bereich.
**Empfehlung:** Nachschlag in einer Folge-Iteration mit Schwerpunkt Statistik/Auswertung,
Passwortmanager, Telefonie/TAPI und den Fremd-API-Anbindungen.
---
## HYP-002 — Erzwingung der Transportverschlüsselung
**Betroffene Anforderung:** SyRS-033 (Transportverschlüsselung und Zertifikatskonfiguration)
**Beobachtung:** `WebServiceConfig` enthält die Felder `WebServiceCertificateFilePath` und
`WebServiceCertificatePassword`; `appsettings.Production.json` des Nexus enthält
`Host.LinuxCertificatePath` und `Host.LinuxCertificatePassword`. Sämtliche mitgelieferten
Beispielkonfigurationen verwenden `http://` und leere Zertifikatsfelder.
**Aussage [HYPOTHESE]:** Bei hinterlegtem Zertifikat werden unverschlüsselte Aufrufe abgewiesen
oder auf HTTPS umgeleitet.
**Fehlende Information:** Der Kestrel-/Host-Konfigurationscode, der die Endpunkte aus diesen
Feldern aufbaut, wurde nicht gelesen. Es ist unbekannt, ob ein HTTP-Endpunkt parallel bestehen
bleibt, ob HSTS oder eine Umleitung aktiv ist und ob TLS-Mindestversionen gesetzt werden.
**Offene Frage an den Fachexperten:** Wird in Produktivinstallationen HTTPS erzwungen, oder ist
der Betrieb über HTTP in Kundennetzen üblich? Existiert ein vorgelagerter Reverse Proxy, der die
Terminierung übernimmt (die Auswertung von `X-Forwarded-For` in `TicketAuthenticationHandler`
legt dies nahe)?
---
## HYP-003 — Terminierung der Nummernreservierungsschleife
**Betroffene Anforderung:** SwRS-011 (Kollisionsfreie Nummernreservierung ohne Sperrung)
**Beobachtung:** `NumberGroupBL.GetNextNumber` enthält ein `while (true)` ohne Abbruchbedingung,
ohne Versuchszähler und ohne Wartezeit zwischen den Versuchen. Verlassen wird die Schleife nur,
wenn das bedingte `UPDATE` genau eine Zeile ändert.
**Aussage [HYPOTHESE]:** Die Schleife terminiert auch unter hoher Nebenläufigkeit in endlicher Zeit.
**Fehlende Information:** Es liegt kein Lasttest und keine Betriebsstatistik vor. Ebenfalls
unbekannt ist, ob die zusätzlich in `FindNextNumber` enthaltene innere `while`-Schleife (die
so lange zählt, bis eine in der Zieltabelle unbenutzte Nummer gefunden ist) bei großen Lücken
zu Laufzeitproblemen führt – sie führt je Schritt eine eigene `SELECT COUNT(*)`-Abfrage aus.
**Offene Frage an den Fachexperten:** Sind in der Praxis Hänger oder auffällige Wartezeiten bei
der Belegnummernvergabe bekannt, insbesondere bei Mandanten mit großen Nummernbereichen oder
vielen gleichzeitigen Anwendern?
---
## HYP-004 — Schutz bereits fakturierter Servicezeiten
**Betroffene Anforderung:** StRS-009 (Leistungszeiterfassung und Fakturierung von Servicezeiten)
**Beobachtung:** `CentronRights.md` (KONTEXT) beschreibt zu den Rechten „Helpdeskzeiten
verschieben" und „Helpdeskzeiten löschen" jeweils den Zusatz „But only if the ticket is not part
of a receipt." Im gelesenen Code (`HelpdeskTimerBL.cs:556`) wurde nur die Rechteprüfung
`DELETE_HELPDESK_TIMER` bestätigt, nicht jedoch die Prüfung auf Belegzugehörigkeit.
**Aussage [HYPOTHESE]:** Das Verschieben und Löschen einer Zeiterfassung ist technisch gesperrt,
sobald die Zeit Teil eines Belegs ist.
**Fehlende Information:** Vollständige Lektüre von `HelpdeskTimerBL` (36 KB),
`ReceiptItemTimerBL` (104 KB) und `TimerBillingBL` (32 KB) hinsichtlich einer Prüfung auf
`HelpdeskTimerBillingState` bzw. eine Belegreferenz.
**Offene Frage an den Fachexperten:** Ist diese Sperre fachlich zwingend (Konsistenz der
Fakturierung) und wird sie im Betrieb tatsächlich beobachtet? Für die Zielarchitektur ist dies
eine abrechnungsrelevante Integritätsregel.
---
## HYP-005 — Sicherheitsauswirkung der Ticketübergabe im Query-String
**Betroffene Anforderung:** SwRS-026 (Ticketprüfung als ASP.NET-Core-Authentifizierungsschema)
**Beobachtung:** `TicketAuthenticationHandler.GetTicket()` prüft **zuerst** den Query-Parameter
`access_token` und erst danach den `Authorization`-Header.
**Aussage [HYPOTHESE]:** Die Übergabe im Query-String führt dazu, dass gültige Sitzungstickets
in Zugriffsprotokollen von Webservern, Reverse Proxies oder Browserhistorien erscheinen.
**Fehlende Information:** Es ist nicht belegt, welche Clients diesen Weg tatsächlich nutzen
(vermutlich SignalR-Verbindungen, da diese keine Header setzen können) und ob die Protokollierung
der Query-Zeichenkette in den Betriebsumgebungen aktiv ist.
**Offene Frage an den Fachexperten:** Wird der Query-String-Weg produktiv benötigt? Falls ja,
sollte im Zielsystem ein kurzlebiges, auf den Verbindungsaufbau beschränktes Token verwendet
werden.
---
## HYP-006 — Vollständigkeit der Doppelimplementierung BL/WS
**Betroffene Anforderung:** SyRS-041 (Umschaltbare Datenzugriffsart des Fachclients)
**Beobachtung:** `docs/getting-started/general-structure.md` verlangt ausdrücklich, dass jedes
Modul beide Datenzugriffswege implementiert. Im Verzeichnis `src/centron/Centron.WPF.UI/Services`
liegen 688 Dateien. Es wurde nicht geprüft, ob zu jeder `I*Logic`-Schnittstelle tatsächlich
sowohl eine `BL*`- als auch eine `WS*`-Implementierung existiert.
**Aussage [HYPOTHESE]:** Alle Clientmodule sind sowohl mit direktem Datenbankzugriff als auch
über den Web-Service lauffähig.
**Fehlende Information:** Automatisierter Abgleich der Schnittstellen- und Implementierungsnamen
über alle Module hinweg; zusätzlich die Auswertung der `SupportsConnectionTypes`-Deklarationen
aller `AppModuleController`.
**Offene Frage an den Fachexperten:** Welche Betriebsart ist in der Kundenbasis vorherrschend?
Falls der direkte Datenbankzugriff nur noch selten genutzt wird, entfällt für die
Web-/SaaS-Neuimplementierung ein erheblicher Teil des Migrationsumfangs (siehe K-03 in
`Traceability.md`).
---
## HYP-007 — Inhalt und Steuerbarkeit der Telemetrie
**Betroffene Anforderung:** SyRS-043 (Erhebung und Übermittlung von Betriebstelemetrie)
**Beobachtung:** Es existieren `TelemetryAggregator`, `HttpTelemetryUploadClient`,
`DatabaseGuidProvider`, `HardwareIdProvider`, `ApiCallTelemetryInterceptor`,
`McpToolUsageTelemetryInterceptor`, `CentronAnalytics` sowie die Dienste `TelemetryFlushService`
(1 min) und `TelemetryUploadService` (15 min). Die konkreten Nutzdaten wurden nicht gelesen.
**Aussage [HYPOTHESE]:** Die Telemetrie enthält keine personenbezogenen Daten und kann vom
Betreiber deaktiviert werden.
**Fehlende Information:** Inhalt der übertragenen Datenstruktur, Zieladresse, Rechtsgrundlage
und das Vorhandensein eines Abschaltschalters. Da beide Dienste von `ManagedBackgroundService`
erben, sind sie technisch über `BackgroundServiceBL` abschaltbar – ob dies dem Betreiber im
UI angeboten wird, ist nicht belegt.
**Offene Frage an den Datenschutzbeauftragten und Fachexperten:** Welche Felder werden
übertragen? Existiert eine Auftragsverarbeitungsvereinbarung oder ein Einwilligungsmechanismus?
Für ein SaaS-Zielsystem ist diese Frage neu zu bewerten.
---
## HYP-008 — Vollständiger Aufgabenkatalog des DataQualityService
**Betroffene Anforderung:** SwRS-035 (Aufgabenkatalog der Datenqualitätspflege)
**Beobachtung:** Im Quelltext wurden die ersten drei Aufgaben verifiziert
(`TicketPatternUpdateCustomerMappings`, `ExecuteDirectoryCheck`, `CleanupCentronNotifications`).
Die Aufgaben 4–9 (Checklisten-Kundenzuordnungen, Reorganisation der Profilereinträge,
`ToDoBL.DataQualityFillAccountI3D`, `AccountBL.CheckAndRepairAccountTypeToAccountsTable`,
`HelpdeskTimerBL.DataQualityUpdateMissingHelpdeskTimerProperties`,
`SecondStockArticleBL.DataQualityCleanupSecondaryStockArticles`) stammen ausschließlich aus
`docs/Background Service/DataQualityService.md`.
**Aussage [HYPOTHESE]:** Der Dienst führt genau die neun in der Dokumentation genannten Aufgaben
in der dort angegebenen Reihenfolge aus.
**Fehlende Information:** Lektüre von `DataQualityService.cs` ab Zeile 71 bis zum Ende.
**Bewertung:** Geringes Risiko; die Aussage ist mit vertretbarem Aufwand im Code verifizierbar
und wurde hier nur aus Aufwandsgründen nicht abgeschlossen.
---
## HYP-009 — Belegzustandsmodell in der Entwicklerdokumentation
**Betroffene Anforderung:** SyRS-014 (Belegzustandsmodell mit drei Zuständen)
**Beobachtung:** `docs/reference/receipts/receipts-backend-architecture.md:284-290` beschreibt
vier Belegzustände „Draft – Released – Processed – Cancelled". Der Code definiert in
`ReceiptState` jedoch nur drei Zustände: `Active (offen)`, `Completed (abgeschlossen)`,
`Canceled (storniert)`. Es gibt im Code keinen Hinweis auf „Draft" oder „Released".
**Aussage [HYPOTHESE]:** Die Dokumentation beschreibt einen geplanten oder aus einem anderen
System übernommenen Zustandsraum, der nie implementiert wurde.
**Fehlende Information:** Herkunft der Dokumentationsaussage. Zusätzlich ist unklar, ob der
Belegsperrmechanismus (`TryLockReceipt`) oder das Feld `ReceiptUserStateI3D` (in den Belegsichten
enthalten, siehe `ScriptMethod11803`) einen zweiten, benutzerdefinierten Zustandsraum bildet.
**Offene Frage an den Fachexperten:** Existiert neben `ReceiptState` ein fachlich relevanter,
frei konfigurierbarer Belegstatus (`ReceiptUserState`)? Falls ja, ist er in einer Folge-Iteration
als eigene Anforderung zu erfassen.
**Bewertung:** Dieser Widerspruch ist der Beleg dafür, dass die Entwicklerdokumentation unter
`docs/` in dieser Spezifikation zu Recht durchgängig als `KONTEXT` und nicht als `PRIMÄR`
klassifiziert wurde.
---
## HYP-010 — Wirksamkeit der Rechteänderung innerhalb einer laufenden Sitzung
**Betroffene Anforderung:** SyRS-011 (Auflösung von Benutzerrechten über Gruppenzugehörigkeit),
SwRS-016 (Sitzungsbezogene Zwischenspeicherung von Rechten)
**Beobachtung:** `AppRightsBL.HasUserRight` liest die Rechtemenge über
`Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", …)`. Es wurde keine
Invalidierung dieses Cache-Eintrags bei Rechteänderungen gefunden. Gleichzeitig existiert mit
`CheckRightsFromUser` ein zweiter, nicht gecachter Prüfpfad.
**Aussage [HYPOTHESE]:** Ein Rechteentzug wirkt für einen bereits angemeldeten Benutzer erst
nach Ablauf der Sitzung bzw. nach Neuanmeldung.
**Fehlende Information:** Lebensdauer einer `BLSession` im Web-Service-Betrieb (pro Aufruf oder
pro Sitzung) und das Vorhandensein einer Cache-Invalidierung an anderer Stelle.
**Offene Frage an den Fachexperten:** Ist ein sofort wirksamer Rechteentzug fachlich gefordert
(z. B. bei Freistellung eines Mitarbeiters)? Für ein SaaS-Zielsystem ist dies eine
sicherheitsrelevante Entwurfsentscheidung.
---
## HYP-011 — Reichweite der optimistischen Nebenläufigkeitsprüfung
**Betroffene Anforderung:** SyRS-017 (Schutz vor konkurrierenden Belegänderungen)
**Beobachtung:** Die Prüfung `if (concurrencyControlGuid != null && receipt.ConcurrencyControlGuid
!= concurrencyControlGuid)` wurde an sieben Stellen in `ReceiptBL` gefunden – ausschließlich in
Einzelfeld-Änderungsmethoden (Zahlung, Einkaufspreis, kommissionierte Menge u. a.). Im
allgemeinen Speicherpfad `SaveReceipt<T, TReceiptItem>` wurde keine entsprechende Prüfung
gefunden; dort greift stattdessen die Versionsnummernvalidierung und die pessimistische Sperre.
**Aussage [HYPOTHESE]:** Der allgemeine Speicherpfad ist durch die Kombination aus
Versionsnummernvalidierung und pessimistischer Belegsperre gegen Datenverlust bei
konkurrierender Bearbeitung ausreichend geschützt.
**Fehlende Information:** Verhalten bei Umgehung der Sperre (z. B. abgestürzter Client, dessen
Sperre über `UnLockReceipt(..., onlyIfLockedByCurrentUser: false)` aufgehoben wird) sowie das
Verhalten bei gleicher Versionsnummer (Fall `isCurrentVersion`, in dem eine Änderung ohne
Versionsanhebung gespeichert wird).
**Offene Frage an den Fachexperten:** Sind Fälle bekannt, in denen Belegänderungen ohne
Fehlermeldung verloren gingen? Diese Frage betrifft unmittelbar die Zuverlässigkeit des
Zielsystems.
---
## HYP-012 — Belastbarkeit der aus `docs/` übernommenen Strukturaussagen
**Betroffene Anforderungen:** StRS-015, SwRS-006, SwRS-007, SwRS-008, SwRS-046, SyRS-024
**Beobachtung:** Mehrere Struktur- und Tabellenaussagen stützen sich in Teilen auf die
Entwicklerdokumentation, insbesondere: die vollständige Liste der Tabellen-/Sicht-/Versionspaare
über alle sieben Belegarten, die `AnlageArt`-Codes der gemeinsamen Logtabelle (1 = Angebot,
2 = Auftrag, 3 = Lieferschein, 4 = Rechnung, 5 = Abholschein, 6 = Gutschrift, 22 = Vertrag),
die Liste der `SaveReceipt*Repository`-Klassen sowie die EDI-Formatliste und die
`EDILogState`-Werte. Im Code stichprobenartig verifiziert wurden davon: das Lieferschein-Paar
(`LiefKopf`/`LiefKopfVersions` → `DeliveryLists`/`DeliveryListVersions`, über
`ScriptMethod11803`), die Belegartcodes über `CentronObjectKindNumeric` und die Existenz der
lieferantenspezifischen EDI-Partial-Dateien.
**Aussage [HYPOTHESE]:** Die nicht einzeln verifizierten Struktur- und Codeaussagen der
Entwicklerdokumentation treffen zu.
**Fehlende Information:** Ein maschineller Abgleich des tatsächlichen Datenbankschemas (Tabellen,
Sichten, Spalten) gegen die Dokumentation. Ein Datenbankschema-Abzug lag im Arbeitsverzeichnis
nicht vor; die Struktur ist nur indirekt über die 764 Migrationsskripte rekonstruierbar.
**Offene Frage an den Fachexperten:** Kann für die Folge-Iteration ein Schemaabzug
(Tabellen-, Spalten- und Constraint-Liste) bereitgestellt werden? Das würde die überwiegende
Mehrheit der `KONTEXT`-Belege im Datenmodellbereich durch `PRIMÄR`-Belege ersetzen und ist die
wirkungsvollste Einzelmaßnahme zur Erhöhung der Belegqualität.
---
## Übersicht
| ID | Kurzbezeichnung | Betroffene Anforderung(en) | Risiko für die Migration |
|---|---|---|---|
| HYP-001 | Nicht analysierte Module | Vollständigkeit gesamt | hoch (Umfangsschätzung) |
| HYP-002 | Erzwingung von TLS | SyRS-033 | mittel (Sicherheit) |
| HYP-003 | Terminierung der Nummernschleife | SwRS-011 | mittel (Zuverlässigkeit) |
| HYP-004 | Schutz fakturierter Zeiten | StRS-009 | hoch (Abrechnungsintegrität) |
| HYP-005 | Ticket im Query-String | SwRS-026 | mittel (Sicherheit) |
| HYP-006 | Vollständigkeit BL/WS-Doppelpfad | SyRS-041 | hoch (Migrationsumfang) |
| HYP-007 | Telemetrieinhalt und Opt-out | SyRS-043 | mittel (Datenschutz) |
| HYP-008 | Aufgaben 4–9 der Datenqualität | SwRS-035 | gering |
| HYP-009 | Widerspruch Belegzustandsmodell | SyRS-014 | mittel (Fachmodell) |
| HYP-010 | Sofortwirksamkeit von Rechteentzug | SyRS-011, SwRS-016 | hoch (Sicherheit) |
| HYP-011 | Reichweite des Nebenläufigkeitsschutzes | SyRS-017 | hoch (Datenverlust) |
| HYP-012 | Nur dokumentierte Schemaaussagen | StRS-015, SwRS-006/-007/-008/-046, SyRS-024 | hoch (Datenmodell) |
@@ -0,0 +1,568 @@
# StRS – Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Ebene:** Stakeholder Requirements (ISO/IEC/IEEE 29148:2018, Kap. 9.2)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Erstellt:** 2026-08-25 · Reverse Requirements Engineering, rein statische Analyse
**Sprache:** Anforderungsaussagen deutsch; technische Bezeichner in Originalsprache
---
## 0. Vorbemerkung zur Lesart
Jede Anforderung trennt strikt zwischen `Fakt` (was im Artefakt nachweisbar steht) und `Aussage`
(fachliche Interpretation). Belege sind klassifiziert als `PRIMÄR` (durchgesetzte Regel in Code
oder DB-Constraint), `SEKUNDÄR` (UI-Text, Fehlermeldung, Mapping, Konfigurationsschalter) und
`KONTEXT` (Kommentar, Commit, Ticketreferenz, Entwicklerdokumentation).
Die Entwicklerdokumentation unter `docs/` ist durchgängig als `KONTEXT` klassifiziert, weil sie
nicht ausführbar ist und mindestens an einer Stelle nachweislich vom Code abweicht (siehe
`Analysebericht.md`, Abschnitt „Widersprüche").
Alle Pfadangaben sind relativ zum Wurzelverzeichnis der Codebasis.
---
## 1. Akteure und Stakeholder
Die folgenden Akteure sind aus den Authentifizierungs- und Rechtestrukturen ableitbar und werden
in den Anforderungen konsistent verwendet:
| Akteur | Technische Entsprechung | Beleg |
|---|---|---|
| **Interner Benutzer (Mitarbeiter)** | `AppUser` (Tabelle `Sichbenu`), verknüpft mit `EmployeeCompact` | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:157-218` |
| **Web-Account (Kunde des Kunden)** | `WebAccount`, eigene Rechtetabelle `WebAccountsRights` | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:679-691` |
| **Administrator** | Mitglied der Gruppe „Administratoren" (`AppGroup.I3D == 6`) | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:359-360` |
| **Systemintegrator / Fremdanwendung** | `ApplicationKind` mit eigener Lizenz-GUID, Login am Web-Service | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| **API-Client (technisch)** | `AccessToken` (persönlicher Token, SHA-256-Hash) | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:377-400` |
| **Hintergrunddienst** | `ManagedBackgroundService`-Ableitungen im Web-Service | `src/webservice/Centron.Host/AspNetCore/HostedServices/` |
| **Lizenzgeber (NEXOWARE)** | Lizenzserver / `c-entron Office`, `LicenseManager` | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs` |
| **Distributor / Lieferant (EDI-Partner)** | `SupplierEdiConfigurations`, `SupplierEdiBL.*` | `src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs` |
| **Finanzbuchhaltung / Steuerberater** | `BookKeepingExportBL`, DATEV-Online-Paket | `src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs:1560` |
| **Bank / Zahlungsdienstleister** | finAPI-Anbindung | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
---
## 2. Anforderungen
```
ID: StRS-001
Titel: Mandanten- und filialfähiger Geschäftsbetrieb
Ebene: StRS
Typ: funktional
Akteur: Administrator, Interner Benutzer
Vorbedingung: Ein Mandant (Mandator) ist als Default gekennzeichnet; optional sind Filialen (Branch) angelegt.
Fakt: `MandatorBL.GetDefaultMandator()` selektiert genau den Mandator mit `Default == 1`. `NumberGroupBL.RefreshAllNumberGroups()` legt für den Default-Mandanten und zusätzlich für jede Filiale (ohne Hauptsitz) eigene Nummernkreise an. `ReceiptBase` führt die Felder `BranchI3D` und `BranchOrigin`; `CentronObjectKindNumeric` kennt die Objektarten `Company = 53 // Mandant` und `Branch = 124`.
Aussage: Das System soll den Geschäftsbetrieb eines Mandanten mit optional mehreren Filialen abbilden, wobei Filialen eigene Nummernkreise erhalten und jeder Beleg einer Filiale zugeordnet werden kann.
Ergebnis: Belege, Nummernkreise und Sichtbarkeitsregeln sind eindeutig einem Mandanten und optional einer Filiale zugeordnet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/MandatorBL.cs:19-22 (`GetDefaultMandator`) – Begründung: Der Code setzt die Existenz genau eines Default-Mandanten als Systeminvariante voraus.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152 (`RefreshAllNumberGroups`) – Begründung: Erzeugt Nummernkreise je Filiale und belegt damit die Filialfähigkeit der Belegnummerierung.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:19-20 (`BranchI3D`, `BranchOrigin`) – Begründung: Jeder Beleg trägt eine Filialzuordnung im Datenmodell.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:31-32 (`Company = 53 // Mandant`, `Branch = 124`) – Begründung: Mandant und Filiale sind eigenständige, systemweit adressierbare Objektarten.
Prüfidee: Zwei Filialen anlegen, in jeder Filiale je eine Rechnung erzeugen und prüfen, dass die Nummernvergabe aus getrennten `NumberGroup`-Datensätzen erfolgt (unterschiedliche `Current`-Werte).
Tracelinks: SyRS-015, SyRS-012
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Rollenbasierte Zugriffssteuerung für interne Benutzer
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Benutzer ist am System angemeldet und Mitglied mindestens einer Rechtegruppe.
Fakt: Rechte werden nicht direkt an Benutzer, sondern über Gruppen vergeben: `AppRightsBL.GetAllAppRightsFromUser` liest per SQL `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `UserRightsConst` definiert über 1 000 Rechtekonstanten in einer hierarchischen Klassenstruktur (u. a. `Sales.Customer.Helpdesk`, `Administration.UserRightsManagement`, `Controlling.Finances`).
Aussage: Das System soll Zugriffsrechte ausschließlich über Rechtegruppen an interne Benutzer vergeben und für jede fachliche Funktion ein eigenes, feingranulares Recht führen.
Ergebnis: Ein Benutzer besitzt genau die Vereinigungsmenge der Rechte aller Gruppen, denen er angehört; ohne Gruppenzugehörigkeit besitzt er keine Rechte.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:651-664 (`GetAllAppRightsFromUser`) – Begründung: Zeigt die durchgesetzte Auflösung Benutzer→Gruppe→Recht auf Datenbankebene.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:63-87 (`GetRightsFromCurrentUser`) – Begründung: Bildet dieselbe Regel objektorientiert über `AppUser.Groups` ab.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (gesamte Datei, u. a. Zeilen 2189-2389) – Begründung: Katalog der fachlich unterscheidbaren Rechte je Belegart und Modul.
- [KONTEXT] docs/guides/development/check-userrights.md – Begründung: Entwicklerdokumentation beschreibt die drei Prüfstellen (ViewModel, ModuleRegistration, BL) und bestätigt die Absicht.
Prüfidee: Benutzer aus allen Gruppen entfernen; anschließend muss `AppRightsBL.HasUserRight(userI3D, beliebigesRecht)` durchgängig `false` liefern und jeder rechtebewehrte Aufruf mit `DefaultMessageCodes.RightCheckFailed` scheitern.
Tracelinks: SyRS-011, SyRS-012, SwRS-016, SwRS-017, SwRS-018
Konsolidierung: Kandidat: StRS-003 (Web-Account-Rechte bilden ein zweites, strukturell paralleles Rechtesystem)
Status: belegt
```
```
ID: StRS-003
Titel: Kundenselbstbedienung über getrenntes Web-Account-Rechtesystem
Ebene: StRS
Typ: funktional
Akteur: Web-Account (Kunde des Kunden)
Vorbedingung: Für einen Kunden ist im Adressstamm ein Web-Account angelegt.
Fakt: Es existiert ein vom Mitarbeiter-Rechtesystem vollständig getrennter Rechtekatalog `WebAccountRightsConst` (u. a. `WEBRIGHT_CREATEREQUEST = 26000`, `WEBRIGHT_SHOWALLINVOICES = 61001`, `WEBRIGHT_SHOWONLYOWNINVOICES = 61002`). Die Auflösung erfolgt über `SELECT WebRightsI3D FROM WebAccountsRights WHERE WebAccountsI3D = :WebAccountI3D`. `ReceiptBL.CanUserViewReceipt` verweigert Web-Account-Logins den Belegzugriff generell.
Aussage: Das System soll Endkunden über ein eigenständiges Web-Account-Konto Selbstbedienungsfunktionen (Ticketerfassung, Belegeinsicht, Shop) anbieten, deren Berechtigungen unabhängig vom Mitarbeiter-Rechtesystem verwaltet werden.
Ergebnis: Ein Web-Account sieht ausschließlich die ihm über `WebAccountsRights` freigeschalteten Daten und hat keinen Zugriff auf die interne Belegbearbeitung.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/WebAccountRightsConst.cs:9-79 – Begründung: Eigener, disjunkter Rechte-Nummernraum für Web-Accounts.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:666-691 (`HasWebAccountRight`, `GetAllWebRightsFromWebAccount`) – Begründung: Getrennter Auswertungspfad gegen `WebAccountsRights`.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (`CanUserViewReceipt`: „Web-Benutzer haben keine Berechtigung Belege einzusehen.") – Begründung: Explizite, durchgesetzte Abgrenzung der beiden Akteursklassen.
- [SEKUNDÄR] README.md:31-36 (Abschnitt „WebCart") – Begründung: Beschreibt den WebCart als Funktion „primarily intended for the customers of our customers" und den Login als Web-Account.
Prüfidee: Mit einem Web-Account anmelden und `GetReceiptByI3D` aufrufen; der Aufruf muss mit `RightCheckFailed` und der Meldung „Web-Benutzer haben keine Berechtigung Belege einzusehen." abgewiesen werden.
Tracelinks: SyRS-013, SwRS-041
Konsolidierung: Kandidat: StRS-002 (zwei parallele Rechtemodelle mit gleicher fachlicher Absicht; Zusammenführung im Zielsystem prüfen)
Status: belegt
```
```
ID: StRS-004
Titel: Lizenzabhängiger Funktionsumfang
Ebene: StRS
Typ: nicht-funktional (Geschäftsmodell)
Akteur: Lizenzgeber (NEXOWARE), Administrator
Vorbedingung: Der Web-Service kann eine Lizenzdatei vom Lizenzserver beziehen oder besitzt eine gültige zwischengespeicherte Lizenz.
Fakt: `LicenseManager.HasLicense(Guid)` und `GetLicenseCount(Guid)` steuern die Verfügbarkeit einzelner Funktionen. `ApplicationKind` bindet jede anmeldefähige Anwendung an eine Lizenz-GUID; `CheckLicense` prüft zusätzlich Versionsgültigkeit und Anzahl gleichzeitig genutzter Lizenzen. `AccessTokenBL.ValidateToken` verweigert die Tokenprüfung ohne `LicenseGuids.AccessTokenModule`; `AuthenticatorFactory` verweigert OpenID-Connect ohne `LicenseGuids.OpenIDConnectAuthentication`.
Aussage: Das System soll den nutzbaren Funktionsumfang und die Anzahl gleichzeitiger Anmeldungen anhand einer serverseitig geprüften Lizenz steuern.
Ergebnis: Nicht lizenzierte Module bleiben verborgen oder liefern eine Lizenzfehlermeldung; bei Erreichen der Lizenzanzahl wird die Anmeldung mit `DefaultMessageCodes.LicenseMaximumReached` abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302 (`CheckLicense`) – Begründung: Prüft Lizenzbesitz, Versionsgültigkeit und Ticketanzahl gegen `GetLicenseCount`.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:382-383 – Begründung: Harte Lizenzsperre für das Access-Token-Modul.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:132-133 – Begründung: Harte Lizenzsperre für OpenID Connect.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53 – Begründung: Vollständige Registrierung aller anmeldefähigen Produkte mit Lizenz-GUID, `ExpirationKind` und `LicenseUsageKind`.
- [KONTEXT] docs/reference/security/licensing-system.md – Begründung: Erläutert Lizenzmodell (GUID, count, valid until date/version) und bestätigt die Interpretation.
Prüfidee: Lizenzdatei ohne `LicenseGuids.PasswordManager` einspielen; das Passwortmanager-Modul darf im Client nicht registriert werden und der zugehörige Web-Service-Aufruf muss eine Lizenzfehlermeldung liefern.
Tracelinks: SyRS-007, SwRS-020, SwRS-021, SwRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Durchgängiger Verkaufsbelegfluss
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertrieb, Innendienst)
Vorbedingung: Ein Kunde (Account/Kunde) ist im Stammdatenbestand angelegt.
Fakt: Es existieren sieben Kundenbelegarten mit einheitlicher Basisklasse `ReceiptBase`: Angebot (`OfferClass = 1`), Auftrag (`OrderClass = 2`), Lieferschein (`DeliveryListClass = 3`), Rechnung (`InvoiceClass = 4`), Abholschein (`PickupListClass = 5`), Gutschrift (`CreditVoucherClass = 6`), Vertrag (`ContractClass = 22`). `CentronObjectKindNumericExtensions.IsCustomerReceipt` fasst genau diese sieben Arten zusammen. `ReceiptWebServiceBL.ForwardReceipt` und `CanForwardReceiptsInto` realisieren die Belegweiterführung.
Aussage: Das System soll den Verkaufsprozess über die sieben Kundenbelegarten Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift und Vertrag abbilden und die Weiterführung eines Belegs in einen Folgebeleg unterstützen.
Ergebnis: Aus einem Beleg lassen sich Folgebelege mit Positionsübernahme erzeugen; die Herkunft bleibt über Positionsverknüpfungen nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:273-287 (`IsCustomerReceipt`) – Begründung: Definiert normativ die Menge der Kundenbelegarten.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2315-2336 (`CanForwardReceiptsInto`, `ForwardReceipt`) – Begründung: Belegt die implementierte Weiterführungslogik inkl. Übernahmeoptionen.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ (Unterordner `Offers`, `Orders`, `DeliveryLists`, `Invoices`, `PickupLists`, `CreditVouchers`, `ContractLists`) – Begründung: Je Belegart existieren Kopf-, Positions- und Versionsentitäten.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:307-315 (`GetAssetName`: „Angebot", „Auftrag", „Lieferschein", „Abholschein", „Rechnung", „Gutschrift", „Vertrag", „Stammblatt") – Begründung: Fachliche deutsche Benennung der Belegarten im UI.
Prüfidee: Angebot anlegen, in Auftrag weiterführen, Auftrag in Lieferschein, Lieferschein in Rechnung; nach jedem Schritt muss der Ursprungsbeleg die verarbeitete Menge (`QuantityProcessed`) erhöht haben.
Tracelinks: SyRS-014, SyRS-018, SwRS-004, SwRS-009
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Beschaffungsprozess mit Lieferantenbelegen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Einkauf)
Vorbedingung: Ein Lieferant (Kreditor) ist angelegt.
Fakt: `IsSupplierReceipt` umfasst Anfrage (`SupplierOffer = 15`), Bestellung (`SupplierOrder = 7`), Wareneingang (`SupplierDeliveryList = 8`), WE-Kalkulation (`SupplierInvoice = 18`) und Lieferantengutschrift (`SupplierCreditVoucher = 148`). Für jede Art existieren eigene Entitäten unter `Entities/Sales/Receipts/Supplier*` sowie eigene Nummernkreise (`NumberGroupEnum.Inquiry`, `PurchaseOrder`, `Intake`, `VendorInvoice`, `SupplierCreditVoucher`).
Aussage: Das System soll den Beschaffungsprozess über die fünf Lieferantenbelegarten Anfrage, Bestellung, Wareneingang, WE-Kalkulation und Lieferantengutschrift abbilden.
Ergebnis: Bestellungen, Wareneingänge und Lieferantenrechnungen sind als eigenständige, nummerierte Belege gespeichert und miteinander referenzierbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:289-301 (`IsSupplierReceipt`) – Begründung: Normative Definition der Lieferantenbelegarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:40-55 und 106-117 – Begründung: Eigene Nummernkreise mit Zuordnung zu den Tabellen `AnfrKopf`, `BestKopf2`, `WareKopf`, `KalkKopf`, `LiGutKopf`.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:139-147 (Descriptions „Bestellung", „Wareneingang", „WE-Kalkulation", „Li.-Gutschrift") – Begründung: Fachliche Benennung im UI.
Prüfidee: Bestellung anlegen und in einen Wareneingang überführen; die Bestellnummer muss aus dem Nummernkreis `PurchaseOrder` (Tabelle `BestKopf2`, Feld `Nummer`) stammen.
Tracelinks: SyRS-015, SyRS-019, SyRS-024
Konsolidierung: Kandidat: StRS-005 (Kunden- und Lieferantenbelege teilen sich `ReceiptBase`, unterscheiden sich aber in Persistenz und Nummernkreisen)
Status: belegt
```
```
ID: StRS-007
Titel: Vertragsgeschäft mit wiederkehrender Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertragsverwaltung), Hintergrunddienst
Vorbedingung: Ein Vertrag (`ReceiptContract`) ist mit Abrechnungsintervall und Kalkulationsart angelegt und aktiv.
Fakt: `AutomaticFacturaBL.GetActiveContracts` selektiert Verträge mit `State == 1` und wertet `CalculationKind` (`ContractCalculationKind.Auto`, `Need`, manuell), `AutomatedProlongation`, `FirstPaidDate`, `LastPaidDate`, `ContractBegin`, `ContractEnd`, `BillingIntervalKind`/`BillingIntervalDuration` sowie `ContractExtraKind` (`Easy`, `ClickDevice`, `Contingent`) aus. `ContractCloseService` und `ContractEndeService` laufen täglich.
Aussage: Das System soll Verträge mit definiertem Abrechnungsintervall führen und daraus periodisch Rechnungen erzeugen, wobei automatische, bedarfsgesteuerte und manuelle Abrechnungsarten sowie Kontingent- und Klickverträge unterschieden werden.
Ergebnis: Zum Abrechnungslauf werden genau die fälligen Verträge selektiert und in Rechnungen überführt; das Abrechnungsergebnis wird protokolliert (`StoreBillingResult`).
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845 (`GetActiveContracts`) – Begründung: Enthält die vollständige, durchgesetzte Selektionsregel für fällige Verträge.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:2101-2118 (`StoreBillingResult`) – Begründung: Belegt die verpflichtende Protokollierung jedes Abrechnungsergebnisses.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ContractCloseService.cs:32 und ContractEndeService.cs:22 (`TimeSpan.FromDays(1)`) – Begründung: Tagesgenauer Zyklus der vertragsbezogenen Hintergrundverarbeitung.
- [KONTEXT] docs/reference/receipts/contracts-backend.md – Begründung: Beschreibt Kontingentverwaltung, Klickzählerverträge und automatische Verlängerung.
Prüfidee: Vertrag mit `BillingIntervalKind = Monthly`, `BillingIntervalDuration = 1`, `AutomatedBilling = true` und `FirstPaidDate` in der Vergangenheit anlegen; `SearchBillingContracts` mit `IsActiveOnly = false` muss den Vertrag genau einmal je fälliger Periode liefern.
Tracelinks: SyRS-022, SwRS-032
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Ticketgestützter Servicebetrieb (Helpdesk)
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Servicetechniker, Disponent), Web-Account
Vorbedingung: Der Benutzer besitzt das Recht `SHOW_HELPDESK`; Ticketstatus, -typen und -kategorien sind als Stammdaten gepflegt.
Fakt: Tickets werden in `hlpdsk_requests` geführt (Nummernkreis `NumberGroupEnum.Helpdesk`) und besitzen konfigurierbare Status (`HelpdeskStateI3D`), Prioritäten, Typen sowie Haupt- und zwei Unterkategorien. Der Abschlussstatus ist nicht hart kodiert, sondern über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfigurierbar. Der Rechtekatalog `UserRightsConst.Sales.Customer.Helpdesk` umfasst u. a. Anzeigen, Anlegen, Bearbeiten, Abschließen, Fälligkeit ändern, Zeiten bearbeiten, Sichtbarkeit ändern, Checklisten und Ticketvorlagen.
Aussage: Das System soll Serviceanfragen als Tickets mit frei konfigurierbarem Statusmodell, Kategorisierung, Verantwortlichkeiten und Fälligkeitsterminen führen und den Zugriff darauf über eigene Rechte steuern.
Ergebnis: Jedes Ticket ist eindeutig nummeriert, einem Kunden und einem Status zugeordnet und dokumentiert Bearbeiter, Verantwortlichen und Historie.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:418-466 (`CheckUserRigths`) – Begründung: Zeigt die durchgesetzte Rechteprüfung inkl. konfigurierbarem Abschlussstatus.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:12-120 – Begründung: Vollständiges Ticket-Datenmodell mit Status, Priorität, Typ, Kategorien, Fälligkeit, Verantwortlichem und Zeitsummen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:30-31, 100-103 – Begründung: Eigener Nummernkreis „Helpdesk" auf Tabelle `hlpdsk_requests`.
- [KONTEXT] CentronRights.md:3-130 – Begründung: Beschreibt für jedes Helpdesk-Recht die beabsichtigte fachliche Wirkung in Prosa.
Prüfidee: Benutzer ohne `CLOSE_REQUEST` versucht, ein Ticket auf den in den Einstellungen als „geschlossen" markierten Status zu setzen; der Speichervorgang muss mit „Sie haben nicht das Recht \"Helpdesk abschließen\"." scheitern.
Tracelinks: SyRS-035, SyRS-036, SwRS-043, SwRS-044
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Leistungszeiterfassung und Fakturierung von Servicezeiten
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Servicetechniker), Interner Benutzer (Fakturierung)
Vorbedingung: Ein Ticket existiert; dem erfassenden Mitarbeiter ist ein Mitarbeiterartikel zugeordnet.
Fakt: `HelpdeskTimer`/`HelpdeskTimerBase` bilden Zeiterfassungssätze mit Abrechnungszustand (`HelpdeskTimerBillingState`), Zeitartentypen (`HelpdeskTimerTypes`), Stundensatzzuschlägen (`HelpdeskTimerHourlySurchargeRateOverlap`) und Unterschrift ab. `HelpdeskCompact` führt getrennte Summen für berechenbare, nicht berechenbare, geplante, bereits fakturierte und noch nicht fakturierte Zeiten. `TimerBillingBL` realisiert die Überführung in Belege. Das Verschieben oder Löschen einer Zeit ist laut Rechtebeschreibung nur zulässig, solange das Ticket nicht Teil eines Belegs ist.
Aussage: Das System soll erfasste Servicezeiten je Ticket nach Berechenbarkeit und Abrechnungszustand differenzieren und die Überführung berechenbarer Zeiten in Fakturabelege unterstützen; bereits fakturierte Zeiten dürfen nicht mehr verschoben oder gelöscht werden.
Ergebnis: Fakturierte Zeiten sind gegen Veränderung geschützt; offene berechenbare Zeiten sind pro Kunde/Ticket abrechenbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90 (`HasCalculableTimes`, `CalculableTimesInSeconds`, `NotBilledCalculableNotPlannedTimesInSeconds`, `BilledCalculableNotPlannedTimesInSeconds`) – Begründung: Datenmodell trennt berechenbare von nicht berechenbaren und fakturierte von nicht fakturierten Zeiten.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/TimerBilling/TimerBillingBL.cs – Begründung: Eigene Geschäftslogik zur Fakturierung von Zeiten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs:556 (Rechteprüfung `DELETE_HELPDESK_TIMER`) – Begründung: Löschen von Zeiten ist rechtebewehrt.
- [KONTEXT] CentronRights.md:59-66 („Helpdeskzeiten verschieben … aber nur, wenn das Ticket nicht Teil eines Receipts ist") – Begründung: Beschreibt die beabsichtigte Schutzregel gegen Änderung fakturierter Zeiten.
Prüfidee: Eine Zeit fakturieren und anschließend versuchen, sie auf ein anderes Ticket zu verschieben; der Vorgang muss abgewiesen werden.
Tracelinks: SyRS-035, StRS-008
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – die Sperre „bereits fakturierte Zeiten dürfen nicht mehr verschoben oder gelöscht werden" ist nur über `CentronRights.md` (KONTEXT) belegt und im gelesenen Code nicht verifiziert; siehe HYP-004
```
```
ID: StRS-010
Titel: Lagerbestandsführung mit Seriennummern- und Barcodeverfolgung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Lager, Versand)
Vorbedingung: Artikel sind im Artikelstamm angelegt; mindestens ein Lager (`Stock`) existiert.
Fakt: `ReceiptArticleBookingBL.BookArticles` bucht bei jedem Belegspeichern die Mengendifferenz je Artikelposition; `ValidateArticleWarehouses` prüft für Nebenlager, ob der Artikel dort geführt wird, und meldet andernfalls „Den Artikel '{ArticleCode}' gibt es nicht im Lager '{Caption}'." `ReceiptBarcodeBL` (98 KB) verwaltet belegbezogene Barcodes/Seriennummern; `CheckIfAllNonActiveBarcodesAreStillInTheReceipt` verhindert das Entfernen bereits verarbeiteter Barcodes.
Aussage: Das System soll Lagerbestände je Artikel und Lager führen, bei Belegbuchungen automatisch fortschreiben und seriennummern-/barcodepflichtige Artikel positionsgenau verfolgen.
Ergebnis: Der Lagerbestand entspricht nach jeder Belegspeicherung der Summe der gebuchten Mengendifferenzen; einmal zugeordnete, verarbeitete Barcodes können nicht mehr aus dem Beleg entfernt werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:81-96, 171-236 (`BookArticles`, `BookArticlesForItem`) – Begründung: Enthält die durchgesetzte Mengendifferenz-Buchungslogik.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:125-156 (`ValidateArticleWarehouses`) – Begründung: Durchgesetzte Nebenlagerprüfung vor der Buchung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3667-3674 (`CheckIfAllNonActiveBarcodesAreStillInTheReceipt`) – Begründung: Schutzregel gegen Entfernen verarbeiteter Barcodes.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:149 (Fehlertext) – Begründung: Fachliche Formulierung der Lagerzuordnungsregel.
Prüfidee: Lieferschein mit Artikel im Nebenlager erzeugen, bei dem der Artikel dort nicht geführt wird; das Speichern muss mit der genannten Fehlermeldung scheitern.
Tracelinks: SyRS-019, SwRS-030, SwRS-031
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Gesetzeskonformer elektronischer Rechnungsversand
Ebene: StRS
Typ: Schnittstelle / Compliance
Akteur: Interner Benutzer (Fakturierung), Rechnungsempfänger, Finanzbuchhaltung
Vorbedingung: In den Rechnungseinstellungen ist ein ZUGFeRD-/XRechnung-Profil aktiviert.
Fakt: `ZugferdKind` definiert sechs Formatstufen von `ZUGFeRD_1_0` bis `ZUGFeRD_XInvoice_3_0_1`; die Anzeigetexte nennen explizite Gültigkeitszeiträume („XRechnung 2.2 (gültig ab 01.08.2022)", „XRechnung 3.0.1 | ZUGFeRD 2.3.3 & 2.4 & 2.5 (gültig ab 07.05.2025)"). `InvoiceZugferdBL` setzt je Format die KoSIT-Guideline-IDs (`urn:cen.eu:en16931:2017#compliant#urn:xeinkauf.de:kosit:xrechnung_3.0` etc.) und erzeugt PDF/A-3-konforme Dokumente mit eingebetteter `factur-x.xml`.
Aussage: Das System soll Ausgangsrechnungen zusätzlich als strukturierte elektronische Rechnung im ZUGFeRD-/XRechnung-Format erzeugen und dabei das jeweils vom Betreiber konfigurierte, gesetzlich gültige Profil verwenden.
Ergebnis: Zur Rechnung existiert ein PDF/A-3-Dokument mit eingebetteter, gegen die gewählte Guideline-ID validierbarer XML-Rechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289 (Guideline-IDs je `ZugferdKind`) – Begründung: Belegt die formatgenaue Normkonformität im Code.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:167-228 (`CreateZugferdConformPdfDocument`, `PdfZugferdVersion`, `PdfZugferdConformanceLevel.EN16931`, Dateiname `factur-x.xml`) – Begründung: Belegt PDF/A-3-Einbettung und Konformitätsstufe.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:31-44 – Begründung: UI-Auswahlliste mit gesetzlichen Gültigkeitsdaten, belegt den Compliance-Bezug.
- [SEKUNDÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2394-2446 (`GetReceiptInvoiceSettings`) – Begründung: Konfigurationsschalter für Format, Archivierung und XML-Anhang an E-Mails.
- [KONTEXT] docs/guides/development/xrechnung.md, docs/reference/zugferd-feldzuordnung-anwender.md – Begründung: Verweise auf die offizielle FeRD-/KoSIT-Spezifikation.
Prüfidee: Rechnung mit aktivem Profil `ZUGFeRD_XInvoice_3_0_1` exportieren und die eingebettete `factur-x.xml` mit dem KoSIT-Validator gegen XRechnung 3.0 prüfen; das Ergebnis muss fehlerfrei sein.
Tracelinks: SyRS-023, SwRS-045
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Übergabe an die Finanzbuchhaltung
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Buchhaltung), Steuerberater
Vorbedingung: Buchungsrelevante Belege (Rechnungen, Gutschriften, Lieferantenrechnungen) liegen abgeschlossen vor.
Fakt: `BookKeepingExportBL` stellt `ExportCustomerBookingDataFile` und `NewExportSupplierBookingDataFile` bereit und erzeugt über `GetDatevOnlinePackageForExport(BookKeepingReceipt file, string pdfFileName, DateTime startFinancialYear)` ein DATEV-Online-Paket. Im WPF-Client existieren die Module `DataExchange.BookKeeping` und `DataExchange.DatevOnline2020`.
Aussage: Das System soll Debitoren- und Kreditorenbuchungsdaten in einem von der Finanzbuchhaltung einlesbaren Format exportieren und dabei DATEV-Online-Pakete inklusive Belegbild unterstützen.
Ergebnis: Für einen gewählten Zeitraum liegt eine Exportdatei bzw. ein DATEV-Paket mit Buchungssätzen und zugehörigen Beleg-PDFs vor.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs:832 (`ExportCustomerBookingDataFile`), :1437 (`NewExportSupplierBookingDataFile`), :1560 (`GetDatevOnlinePackageForExport`) – Begründung: Implementierte Exportpfade für beide Buchungskreise inkl. DATEV.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:51,53 (Modulregistrierungen `DataExchange.BookKeeping`, `DataExchange.DatevOnline2020`) – Begründung: Belegt die Bedienbarkeit als eigenständige Anwenderfunktion.
Prüfidee: Buchhaltungsexport für einen Monat mit mindestens einer Rechnung ausführen; die erzeugte Datei muss je Rechnung genau einen Buchungssatz enthalten.
Tracelinks: SyRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Forderungsmanagement mit Mahnstufen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Debitorenbuchhaltung)
Vorbedingung: Es existieren offene, überfällige Rechnungen.
Fakt: `DunningBL` aggregiert offene Rechnungen nach vier Mahnstufen (`DunningLevel.None`, `Level1`, `Level2`, `Level3`) und berechnet je Stufe Anzahl und Bruttobetrag als `GrossPriceComplete - PayedGrossAmount - CreditVoucherGrossAmount`. Ein Mahnstopp ist je Kunde und je Rechnung mit Zeitraum (`DunningStopBegin`, `DunningStopEnd`) und Begründung (`DunningInfo`) setzbar.
Aussage: Das System soll überfällige Forderungen in vier Mahnstufen führen, den offenen Betrag um Zahlungen und Gutschriften bereinigt ermitteln und einen befristeten Mahnstopp je Kunde oder je Rechnung zulassen.
Ergebnis: Ein Mahnlauf berücksichtigt ausschließlich Rechnungen ohne aktiven Mahnstopp und weist je Kunde die höchste erreichte Mahnstufe aus.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231 – Begründung: Definiert die vier Mahnstufen und die Berechnung des offenen Bruttobetrags.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431 (`UpdateDunningStopAndInfo`) – Begründung: Belegt Mahnstopp mit Zeitraum auf Kunden- und Belegebene.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/Invoices/Dunning/ (`DunningRunForCustomer`, `DunningRunItem`, `InvoiceDunning`, `CreditVoucherDunning`) – Begründung: Eigenes Datenmodell für Mahnläufe.
Prüfidee: Rechnung mit Mahnstopp im aktuellen Zeitraum versehen; sie darf im Mahnlauf nicht selektiert werden.
Tracelinks: SyRS-037, SwRS-033
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: EDI-Anbindung an IT-Distributoren
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Einkauf), Distributor/Lieferant, Hintergrunddienst
Vorbedingung: Für den Lieferanten ist eine EDI-Konfiguration mit Format, Dokumentart und Verbindungsdaten hinterlegt.
Fakt: `SupplierEdiBL` (118 KB) ist als Partial-Class-Verbund je Lieferantenformat organisiert (`SupplierEdiBL.Also.cs`, `.AlsoCH.cs`, `.Alltron.cs`, `.Herweck.cs`, `.Komsa.cs`, `.Opentrans.cs`). Der `EdiDownloadService` läuft alle 30 Minuten. Gateway-Bibliotheken existieren unter `src/backend/Centron.Gateway/EDI_EGIS` u. a.
Aussage: Das System soll Auftragsbestätigungen, Lieferavise und Rechnungen von IT-Distributoren automatisiert abrufen, formatabhängig einlesen und mit den eigenen Bestellungen abgleichen.
Ergebnis: Eingelesene Distributordokumente aktualisieren die zugehörige Bestellung; jeder Verarbeitungsvorgang ist protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs (Hauptklasse) sowie die formatbezogenen Partial-Dateien im selben Verzeichnis – Begründung: Implementierte Formatvielfalt je Distributor.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37 (`Task.Delay(TimeSpan.FromMinutes(1))`, Intervall 30 Minuten) – Begründung: Belegt den automatisierten, unbeaufsichtigten Abruf.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:148 (`Purchasing.EDIManagement`) – Begründung: EDI-Konfiguration ist eine Anwenderfunktion.
- [KONTEXT] docs/reference/edi/edi-architecture.md – Begründung: Beschreibt Formate (`OpenTrans21`, `Also`, `AlsoCH`, `Herweck`, `Komsa`, `Alltron`, `Zugferd`), Dokumentarten und Verarbeitungsablauf.
Prüfidee: EDI-Testdatei im OpenTrans-2.1-Format für eine bestehende Bestellung einspielen; die bestätigten Mengen und Liefertermine müssen an der Bestellposition erscheinen und ein Logeintrag mit Status `DownloadOK` entstehen.
Tracelinks: SyRS-024, SwRS-046
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Revisionssichere Nachvollziehbarkeit von Belegänderungen
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Zuverlässigkeit / Wartbarkeit; Compliance)
Akteur: Interner Benutzer, Wirtschaftsprüfer
Vorbedingung: Ein Beleg wurde mindestens einmal gespeichert.
Fakt: `ReceiptBase` führt `Version`, `CreatedByI3D`/`CreatedAt`/`CreatedThroughApplicationVersion` und `ChangedByI3D`/`ChangedAt`/`ChangedThroughApplicationVersion`/`ChangedThroughApplication`. Beim Speichern einer neuen Version ruft `ReceiptBL.SaveReceipt` `SaveReceiptVersion(receipt, previousReceiptVersion)`, wodurch der Vorzustand in die Versionstabelle kopiert wird. `ReceiptLogBL` (74 KB) schreibt feldgenaue Änderungseinträge, z. B. `CreateSetAsPaidEntry`, `CreateContingentValueEntry`.
Aussage: Das System soll jede Belegversion vollständig archivieren und fachlich relevante Feldänderungen mit Zeitpunkt, Benutzer und erzeugender Anwendungsversion protokollieren.
Ergebnis: Zu jedem Beleg ist jede frühere Version rekonstruierbar; Änderungen an abrechnungsrelevanten Feldern sind einzeln nachweisbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:46-52 (Audit-Felder) – Begründung: Datenmodell erzwingt die Erfassung von Urheber, Zeitpunkt und Anwendungsversion.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3595-3634 (Setzen der Audit-Felder, `SaveReceiptVersion`) – Begründung: Durchgesetzte Fortschreibung bei jedem Speichervorgang.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369 (`WriteReceiptLogs`) – Begründung: Feldgenaue Änderungsprotokollierung für Kontingentfelder.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:83-121, 147-204 – Begründung: Beschreibt Versionstabellen als 1:1-Kopien und das gemeinsame Logtabellenkonzept (`AnlageLog` mit `AnlageArt`).
Prüfidee: Beleg zweimal mit unterschiedlichen Positionswerten speichern; in `AngKopfVersions`/`AngPosVersions` (bzw. der jeweiligen Belegart) muss der Vorzustand vollständig vorliegen und `Version` inkrementiert sein.
Tracelinks: SyRS-016, SyRS-031, SwRS-007, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Wahrnehmung von DSGVO-Betroffenenrechten
Ebene: StRS
Typ: Sicherheit / Compliance
Akteur: Administrator (Datenschutzbeauftragter)
Vorbedingung: Der Benutzer besitzt das Recht `DsgvoModule.DSGVO_DELETE_CONTACT` bzw. `ACCESS_CLEANUP_DATABASE`; das DSGVO-Modul ist lizenziert.
Fakt: `DataSecurityBL` bietet `DsgvoDeleteRightGetContacts` und `DsgvoDeleteRightDeleteContacts` mit vorgeschalteter Rechteprüfung. Gelöschte Kontakte werden nicht physisch entfernt, sondern mit dem Text `"DSGVO: Auf Anfrage gelöscht. (Durchgeführt von {0} am {1:d} um {1:t} Uhr)"` überschrieben und deaktiviert. Für Kunden, Lieferanten und Accounts sind die Löschpfade `DoDeleteCustomer`, `DoDeleteSupplier`, `DoDeleteAccount` mit `throw new NotImplementedException(...)` versehen; die zugehörigen SQL-Anweisungen stehen auskommentiert im Quelltext.
Aussage: Das System soll dem Löschbegehren betroffener Personen durch rechtebewehrte Anonymisierung von Ansprechpartnerdaten nachkommen und den Vorgang mit ausführendem Benutzer und Zeitpunkt dokumentieren.
Ergebnis: Personenbezogene Felder des Kontakts sind durch den Anonymisierungstext ersetzt und der Datensatz ist deaktiviert; ein Löschprotokoll wird erzeugt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:377-380, 787-790 (Rechteprüfungen) – Begründung: Durchgesetzte Zugriffsbeschränkung auf die Löschfunktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 (`DsgvoDeletedContactMessage`, `DsgvoDeletedContactMessageWithEmployeeInfo`) – Begründung: Belegt Anonymisierung statt physischer Löschung inkl. Nachweis des Ausführenden.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:856-858, 935-937, 996-998 (`NotImplementedException`) – Begründung: Belegt, dass die Löschung auf Kunden-, Lieferanten- und Accountebene nicht produktiv verfügbar ist.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:12 (`Administration.DSGVO`) – Begründung: Eigenes Anwendermodul.
Prüfidee: DSGVO-Löschung für einen Ansprechpartner ausführen; Name und Kommunikationsdaten müssen anschließend den Anonymisierungstext tragen und `Status` auf 0 stehen. Für einen Kunden muss der Aufruf reproduzierbar mit `NotImplementedException` fehlschlagen.
Tracelinks: SyRS-038, SwRS-047
Konsolidierung: nein
Status: belegt; Workaround – für Kunden/Lieferanten/Accounts ist die Löschung nicht implementiert und muss in der Validierung priorisiert geprüft werden
```
```
ID: StRS-017
Titel: Anbindung an Unternehmens-Identitätsverwaltung und Zwei-Faktor-Authentifizierung
Ebene: StRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Betreiber hat in `WebServiceConfig.xml` bzw. den Anwendungseinstellungen ein Anmeldeverfahren gewählt.
Fakt: `AuthenticatorFactory` unterstützt `SystemAuthenticationMethod.None | Basic | ActiveDirectory | OpenIdConnect` und wählt anhand von `AppUser.AuthentificationKind` einen Fallback-Authenticator. `WebServiceConfig` enthält `ActiveDirectoryAuthEnabled`, `ActiveDirectoryUrl`, `TwoFactorAuthEnabled`, `TwoFactorAuthType` (Standardwert `RadiusServer`), `RadiusServerAddress`, `MailTwoFactorAuthSenderAddress`, `TwoFactorValidDurationInDays`. `BasicAuthenticator` ruft nach erfolgreicher Kennwortprüfung zwingend `TwoFactorAuthBL.ValidateTwoFactor` auf.
Aussage: Das System soll die Benutzeranmeldung wahlweise gegen den lokalen Benutzerstamm, ein Active Directory oder einen OpenID-Connect-Provider durchführen und optional eine Zwei-Faktor-Authentifizierung per RADIUS oder E-Mail erzwingen.
Ergebnis: Eine Anmeldung ist nur erfolgreich, wenn das konfigurierte Primärverfahren und – falls aktiviert – der zweite Faktor bestanden werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:99-147 – Begründung: Vollständige, durchgesetzte Verfahrensauswahl inkl. Lizenz- und Aktivierungsprüfungen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 – Begründung: Zwei-Faktor-Prüfung ist zwingender Teil der Basic-Anmeldung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:7-32 – Begründung: Konfigurationsschalter für AD, RADIUS und Mail-2FA mit Zeitgrenzen.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md – Begründung: Betriebsanleitung für die OIDC-Anbindung.
Prüfidee: `TwoFactorAuthEnabled = true` mit RADIUS setzen; eine Anmeldung mit korrektem Kennwort, aber ohne gültigen zweiten Faktor muss mit `DefaultMessageCodes.TwoFactorAuthFailed` und der Meldung „Die Zwei-Faktor-Authentifizierung ist fehlgeschlagen." abgewiesen werden.
Tracelinks: SyRS-003, SyRS-006, SwRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Unbeaufsichtigte Hintergrundverarbeitung
Ebene: StRS
Typ: funktional / betrieblich
Akteur: Administrator, Hintergrunddienst
Vorbedingung: Der Web-Service läuft und `ExecuteServices` ist aktiviert.
Fakt: Der Web-Service betreibt 33 Hintergrunddienste (Verzeichnis `src/webservice/Centron.Host/AspNetCore/HostedServices`), darunter EDI-Download, automatische Preisaktualisierung, Vertragsabschluss, Eskalationen, Erinnerungen, Datenqualitätspflege, Volltextindizierung, Massenupdates, Telemetrie. Jeder Dienst deklariert über `GetExecutionInterval()` sein Intervall (Sekunden bis 30 Tage) und lässt sich über `BackgroundServiceBL.IsServiceEnabled(serviceName)` einzeln abschalten.
Aussage: Das System soll wiederkehrende fachliche und technische Aufgaben ohne Benutzerinteraktion in definierten Zeitintervallen ausführen und jede dieser Aufgaben zentral aktivierbar bzw. deaktivierbar halten.
Ergebnis: Jeder Dienst führt seine Aufgabe im hinterlegten Intervall aus; Start- und letzte Laufzeit sind persistiert (`UpdateStartTime`, `UpdateLastRunTime`).
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94 – Begründung: Gemeinsame Ausführungsschleife mit Aktivierungsprüfung und Laufzeitpersistenz.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (33 Dienstklassen mit `GetExecutionInterval`) – Begründung: Belegt Umfang und Taktung der automatisierten Verarbeitung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:18 (`<ExecuteServices>false</ExecuteServices>`) – Begründung: Betrieblicher Hauptschalter für die Diensteausführung.
- [KONTEXT] docs/Background Service/DataQualityService.md – Begründung: Beschreibt Zweck und Aufgabenliste eines der Dienste.
Prüfidee: Einen Dienst über `BackgroundServiceBL` deaktivieren; im Log darf innerhalb von 60 Sekunden nach Cachablauf nur noch „… is disabled, skipping execution." erscheinen.
Tracelinks: SyRS-025, SyRS-026, SwRS-034, SwRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-019
Titel: Deutsch als Primärsprache der Bedienoberfläche
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Gebrauchstauglichkeit)
Akteur: Interner Benutzer, Web-Account
Vorbedingung: keine
Fakt: Fehlermeldungen der Geschäftslogik sind durchgängig deutsch formuliert (z. B. „Der Beleg hat kein gültiges Datum.", „Sie haben nicht genügend Rechte um die Gruppe einer anderen Filiale zu löschen.", „Die maximale Anzahl an Lizenzen wurde erreicht."). Lokalisierte Texte liegen als `LocalizedStrings.resx` (deutsch, Basisdatei) und `LocalizedStrings.en.resx` (englisch) vor; es wurden 14 `.resx`-Dateien gefunden.
Aussage: Das System soll alle benutzersichtbaren Texte primär in deutscher Sprache bereitstellen und Englisch als zusätzliche Oberflächensprache unterstützen.
Ergebnis: Ein Benutzer ohne Sprachumstellung erhält ausschließlich deutschsprachige Beschriftungen und Meldungen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3565, 3577 (deutsche Fehlertexte im Code) – Begründung: Deutsche Texte sind fest im Geschäftslogikpfad verankert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:357, 360, 382, 389 – Begründung: Weitere hart kodierte deutsche Fehlermeldungen.
- [SEKUNDÄR] `LocalizedStrings.resx` / `LocalizedStrings.en.resx` (Ressourcendateien der Projekte) – Begründung: Zweisprachiges Ressourcenmodell mit Deutsch als Basis.
- [KONTEXT] docs/getting-started/general-structure.md:114-141 („German-First Language Policy") – Begründung: Explizite Entwicklungsvorgabe.
Prüfidee: Client mit englischer Systemsprache starten; nicht in `LocalizedStrings.en.resx` übersetzte Texte müssen als deutscher Basistext erscheinen (kein Platzhalter, kein Fehler).
Tracelinks: SyRS-028, SwRS-051
Konsolidierung: nein
Status: belegt; Workaround – ein Teil der Meldungen ist hart kodiert statt lokalisiert und ist daher nicht umschaltbar
```
```
ID: StRS-020
Titel: Online-Banking-Anbindung und Zahlungszuordnung
Ebene: StRS
Typ: Schnittstelle
Akteur: Interner Benutzer (Buchhaltung), Bank/Zahlungsdienstleister
Vorbedingung: Eine finAPI-Zugangskonfiguration ist hinterlegt und eine Bankverbindung ist verknüpft.
Fakt: `Centron.APIs.FinAPI` kapselt die finAPI-Schnittstelle mit getrennten Sandbox- und Live-Endpunkten (`https://sandbox.finapi.io`, `https://live.finapi.io`, jeweils zugehörige WebForm-URLs) und OAuth-Client-Credentials- bzw. Client-Password-Grant. `OnlineBankingAccountTransactionsBL` (67 KB) verarbeitet Kontoumsätze; `IncomingPaymentBL` verarbeitet Zahlungseingänge; das Recht `Controlling.Finances.INCOMING_PAYMENT_TRANSACTIONS` steuert den Zugriff.
Aussage: Das System soll Kontoumsätze über einen Bankenaggregator (finAPI) abrufen und diese offenen Rechnungen als Zahlungseingang zuordnen können.
Ergebnis: Zugeordnete Zahlungen setzen den bezahlten Betrag (`PaidFC`) der Rechnung und ändern bei Vollzahlung deren Zustand.
Belege:
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16 – Begründung: Belegt die konkrete Fremdschnittstelle mit Sandbox-/Live-Trennung.
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/RestClient/RestClientBase.cs:145-147 (OAuth-Grant-Typen, `client_secret`) – Begründung: Belegt das Authentifizierungsverfahren gegenüber der Bankschnittstelle.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4920-4958 (`SetAsPaid`-Pfad mit Recht `INCOMING_PAYMENT_TRANSACTIONS`, `PaidFC`, Zustandswechsel) – Begründung: Verknüpft Zahlungseingang mit Belegzustand und Protokollierung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:140 (`OnlineBanking.ConfigurationSettings`) – Begründung: Konfigurierbares Anwendermodul.
Prüfidee: Kontoumsatz mit dem Bruttobetrag einer offenen Rechnung zuordnen; die Rechnung muss anschließend `PaidFC` = Bruttobetrag und `State = Completed` aufweisen, und `ReceiptLog` muss einen `SetAsPaid`-Eintrag enthalten.
Tracelinks: SyRS-014, SyRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-021
Titel: Belegdruck, PDF-Erzeugung und revisionsfeste Ablage
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer
Vorbedingung: Der Beleg ist einem Dokumentenordner (`DirectoryI3D`) zugeordnet und eine Reportgruppe ist konfiguriert.
Fakt: `ReceiptBL.AddReportPdf` legt das erzeugte PDF im Belegordner ab; der Dateiname folgt der Vorlage `"{Belegart} {NUMBER} V{VERSION}.pdf"` oder einem konfigurierten `ReportGroup.CustomExportFilename`. Vor der Ablage prüft `GetIdenticalDocumentInDirectory(directoryI3D, name, reportPdf, receipt.Version)`, ob ein bytegleiches Dokument derselben Version bereits existiert, und gibt in diesem Fall das bestehende Dokument zurück (Kommentar: „Ticket 160276: Avoid storing identical report PDFs multiple times."). Reports werden mit FastReport erzeugt (`FastReport.Net.Pro` unter Windows, `FastReport.Core.Skia` plattformneutral).
Aussage: Das System soll zu jedem Beleg ein versionsbezogenes PDF erzeugen, es im Belegordner ablegen und dabei die mehrfache Ablage inhaltsgleicher Dokumente derselben Belegversion vermeiden.
Ergebnis: Je Belegversion und Report existiert höchstens ein PDF-Dokument im Belegordner.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3459-3503 (`AddReportPdf`, `GetReportAttachmentNameTemplate`) – Begründung: Enthält Ablageregel, Dublettenprüfung und Namenskonvention.
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (PackageReferences `FastReport.Net.Pro`, `FastReport.Core.Skia`) – Begründung: Belegt die eingesetzte Reportengine und die Windows-/Linux-Trennung.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3476 (Kommentar mit Ticketnummer 160276) – Begründung: Weist die Dublettenprüfung als nachträgliche Fehlerbehebung aus.
Prüfidee: Denselben Beleg in derselben Version zweimal als PDF exportieren; im Belegordner darf nur ein Dokument entstehen und beide Aufrufe müssen dieselbe Dokument-I3D liefern.
Tracelinks: SyRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Provisionsermittlung für den Vertrieb
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertriebsleitung)
Vorbedingung: Ein Provisionsschema ist definiert und einem Kunden bzw. Mitarbeiter zugeordnet.
Fakt: Es existieren die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`, `ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionEmployeeGoal`, `ReceiptProvisionEmployeeLevel` und `ReceiptProvisionItemEntity`. `ReceiptProvisionBL` (45 KB) reichert Belege beim Laden über `FillReceiptWithProvision` mit Provisionsdaten an. Der Hintergrunddienst `UpdateExpiredProvisionSchemasService` läuft stündlich. Ein eigener Rechtebereich `UserRightsConst…Provision` existiert.
Aussage: Das System soll Vertriebsprovisionen anhand mitarbeiter- und kundenbezogener Provisionsschemata mit Zielvorgaben und Stufen belegbezogen ermitteln.
Ergebnis: Zu jedem provisionsrelevanten Beleg liegen Provisionsdatensätze je Position vor; abgelaufene Schemata werden automatisch fortgeschrieben.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs (6 Entitäten) – Begründung: Vollständiges Provisionsdatenmodell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7246-7255 (`FillReceiptWithAdditionalData` → `FillReceiptWithProvision`) – Begründung: Provisionsdaten sind fester Bestandteil des geladenen Belegs.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs:45 – Begründung: Automatisierte Pflege abgelaufener Schemata.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:82-84 (`Finances.Receipts.Provision.*`) – Begründung: Eigene Anwendermodule für Schema, Zuordnung und Auswertung.
Prüfidee: Beleg mit einem Artikel speichern, für den ein Provisionsschema greift; `ReceiptProvisionItemEntity` muss genau einen Datensatz je provisionsrelevanter Position enthalten.
Tracelinks: SyRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: RMA- und Reparaturabwicklung
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Service, Lager)
Vorbedingung: Ein Gerät oder Artikel wurde vom Kunden zurückgesandt bzw. soll an den Lieferanten zurückgehen.
Fakt: `RmaBL` (108 KB) verwaltet die Objektarten `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145` und `RmaArticle = 40`. Eigene Nummernkreise bestehen für `RMANumber` (Tabelle `RMA`), `Repairing` (`dbo.Rma`), `RepairEntrance` (`dbo.RmaSendForth`) und `Reshipment` (`dbo.RmaSendBack`). `ReceiptBL.CheckCloseRMADeliverylistReceipt` schließt einen Lieferschein automatisch ab, wenn er RMA-Positionen enthält und der Anwender die Rückfrage bejaht.
Aussage: Das System soll Rücksendungen und Reparaturen kunden- und lieferantenseitig als eigenständige, nummerierte Vorgänge führen und deren Abschluss mit der Lieferscheinabwicklung verknüpfen.
Ergebnis: Ein RMA-Vorgang besitzt eine eigene Nummer; ein aus RMA erzeugter Lieferschein kann ohne Folgerechnung abgeschlossen werden (`ClosedThroughRMA = true`).
Belege:
- [PRIMÄR] src/backend/Centron.BL/CustomerArea/RmaBL.cs – Begründung: Zentrale Geschäftslogik des RMA-Prozesses.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180 (`CheckCloseRMADeliverylistReceipt`) – Begründung: Durchgesetzte Verknüpfung von RMA und Lieferscheinabschluss.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:22-29, 128-133 – Begründung: Getrennte Nummernkreise für Reparatur, Reparatureingang und Rücksendung.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4169-4171 (Dialogtext „Soll der Lieferschein abgeschlossen werden? Falls der Kunde keine Rechnung erhalten soll klicken Sie 'Ja'.") – Begründung: Erläutert die fachliche Bedeutung des Abschlusses.
Prüfidee: Lieferschein mit einer RMA-verknüpften Position speichern und die Abschlussfrage bejahen; der Beleg muss `State = Completed` und `ClosedThroughRMA = true` aufweisen.
Tracelinks: SyRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Betrieb als verteiltes Client-Server-System mit optionaler Containerbereitstellung
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit)
Akteur: Administrator
Vorbedingung: Ein Microsoft SQL Server ist erreichbar.
Fakt: Die Lösung besteht aus einem WPF-Windows-Client (`Centron.WPF.UI`, `net10.0-windows`), einem plattformneutralen Web-Service (`Centron.Host`, `net10.0`, wahlweise als Konsolenanwendung oder Windows-Dienst) und einer Blazor-Webanwendung (`CentronNexus`, `CentronNexus.Host`). `Centron.BL` wird für beide Zielplattformen gebaut (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>`). Eine `compose.yaml` definiert die Dienste `db` (MSSQL), `webservice`, `smtp` und `nexus`; für den Web-Service existiert ein Linux-Dockerfile.
Aussage: Das System soll als verteiltes System aus Windows-Fachclient, plattformneutralem Anwendungsserver und Webanwendung betrieben werden können, wahlweise als Windows-Installation oder als Containerverbund unter Linux.
Ergebnis: Web-Service und Webanwendung sind ohne Windows-Abhängigkeit lauffähig; der Fachclient bleibt Windows-gebunden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>` mit plattformabhängigen PackageReferences, u. a. `SkiaSharp.NativeAssets.Linux`) – Begründung: Belegt die bewusste Doppelzielplattform.
- [PRIMÄR] docker/compose/compose.yaml:1-54 – Begründung: Definiert die vollständige Betriebstopologie inkl. Portzuordnungen.
- [PRIMÄR] src/centron/Centron.WPF.UI/Centron.WPF.UI.csproj (`<TargetFramework>net10.0-windows</TargetFramework>`) – Begründung: Belegt die Windows-Bindung des Fachclients.
- [KONTEXT] docs/guides/services/web-service-on-linux.md – Begründung: Betriebsanleitung für den Linux-Betrieb.
Prüfidee: `docker compose up` ausführen; Web-Service (Port 4321) und Nexus (Port 8050) müssen erreichbar sein und Nexus muss sich am Web-Service anmelden können.
Tracelinks: SyRS-040, SwRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Preisfindung mit kunden- und vertragsspezifischen Sonderkonditionen
Ebene: StRS
Typ: funktional
Akteur: Interner Benutzer (Vertrieb)
Vorbedingung: Für Artikel, Kunde oder Vertrag sind Sonderpreise bzw. Staffelpreise gepflegt.
Fakt: `ReceiptItemPriceBL` wertet in dieser Reihenfolge aus: Vertragssonderpreis (`ContractSpecialPrice` mit `Kind` ∈ {`FixedPrice`, `ChangePurchasePrice`, `ChangeRecommendedSellPrice`, `ChangeSellPrice`, `ChangeListPrice`} und `ChangeKind` ∈ {`Fixed`, `Percentage`}), andernfalls Kundensonderpreis (`CustomerSpecialPrice` mit `SpecialPriceKind` ∈ {`SurchargePurchasePrice`, `ReduceRecommendedSellPrice`, `FixedPrice`, `ReduceSellPrice`, `ReduceListPrice`}), andernfalls Staffelpreis (`ArticleVolumePrices`, nur wenn `UseVolumePrice(contractI3D)`). Ein Kommentar hält fest, dass Vertragswerte invertiert sind („10 is 10 % surcharge, -10 is 10 % discount").
Aussage: Das System soll den Verkaufspreis einer Belegposition in fester Vorrangfolge aus Vertragssonderpreis, Kundensonderpreis und Mengenstaffel ermitteln, wobei sowohl absolute als auch prozentuale Auf- und Abschläge auf unterschiedliche Preisbasen möglich sind.
Ergebnis: Der ermittelte Positionspreis entspricht der höchstrangigen zutreffenden Konditionsregel; ohne Kondition gilt der Artikelstandardpreis.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266 – Begründung: Enthält die vollständige, durchgesetzte Vorrangfolge und alle Konditionsarten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:261-266, 365 (`UseVolumePrice`, `GetArticleVolumePrice`) – Begründung: Staffelpreise greifen nur nachrangig und nur unter Bedingung.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:181 (Kommentar zur Vorzeicheninversion) – Begründung: Erklärt eine nicht selbsterklärende Datenkonvention, die bei einer Migration erhalten oder bewusst geändert werden muss.
- [KONTEXT] docs/reference/receipts/actionprice-system.md – Begründung: Ergänzende Beschreibung des Aktionspreissystems.
Prüfidee: Für einen Artikel gleichzeitig Vertragssonderpreis (fest 100 €), Kundensonderpreis (fest 120 €) und Staffelpreis (90 € ab 10 Stück) hinterlegen; eine Position über 10 Stück im Vertragskontext muss 100 € ergeben.
Tracelinks: SyRS-021, SwRS-029
Konsolidierung: Kandidat: SwRS-029 (mehrere Preisquellen mit gleicher fachlicher Funktion „Sonderkondition"; Vereinheitlichung im Zielsystem prüfen)
Status: belegt
```
@@ -0,0 +1,896 @@
# SyRS – System Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Ebene:** System Requirements (ISO/IEC/IEEE 29148:2018, Kap. 9.3)
**Analysegegenstand:** Gesamte Codebasis unter `C:\DEV\MasterArbeit\QuellCode\CentronERP`
**Erstellt:** 2026-08-25 · Reverse Requirements Engineering, rein statische Analyse
Belegklassifikation und Feldsemantik siehe `StRS.md`, Abschnitt 0. Alle Pfade sind relativ zum
Wurzelverzeichnis der Codebasis. Nicht-funktionale Anforderungen tragen zusätzlich die Zuordnung
zu einem Qualitätsmerkmal nach **ISO/IEC 25010**.
---
## 1. Authentifizierung, Sitzung und Lizenzierung
```
ID: SyRS-001
Titel: Ticketbasierte Authentifizierung am Web-Service
Ebene: SyRS
Typ: Sicherheit
Akteur: Alle Clientanwendungen
Vorbedingung: Der Client kennt Benutzername, Kennwort und die Lizenz-GUID seiner Anwendung.
Fakt: `Authenticator.GetTicket()` authentifiziert den Benutzer, ermittelt über `ApplicationKind.GetKindByLicenseGuid(Auth.ApplicationName)` die aufrufende Anwendung und gibt bei Erfolg eine Ticket-ID zurück. Jeder geschützte Web-Service-Aufruf trägt dieses Ticket im `Request.Ticket`-Feld (WCF-Bridge) bzw. als `Authorization: Bearer <ticket>` oder Query-Parameter `access_token` (ASP.NET-Core-Pfad) und wird durch `AuthenticationTicketBL.GetAuthTicketInfo(token, ipAddress, apiMethod)` validiert. Ist die Anwendungs-GUID unbekannt, wird mit `DefaultMessageCodes.ApplicationIDUnknown` abgewiesen.
Aussage: Das System soll den Zugriff auf Web-Service-Funktionen ausschließlich nach Vorlage eines gültigen, serverseitig geführten Sitzungstickets gewähren, das an Benutzer, Anwendung und Gerät gebunden ist.
Ergebnis: Aufrufe ohne oder mit ungültigem Ticket werden mit `StatusCode.InvalidTicket` bzw. `AuthenticateResult.Fail` abgewiesen; gültige Aufrufe werden ausgeführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:94-155 (`GetTicket`, `AuthenticateUser`) – Begründung: Vollständiger, durchgesetzter Ticket-Ausstellungspfad inkl. Anwendungserkennung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:63-101 – Begründung: Zentrale Ticketprüfung vor jedem attributierten Web-Service-Aufruf.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:44-95, 104-144 – Begründung: Zweiter Prüfpfad für das ASP.NET-Core-Authentifizierungsschema mit Header- und Query-String-Übergabe.
Prüfidee: Web-Service-Methode ohne Ticket aufrufen; Antwort muss `Status = InvalidTicket` und die Meldung „You need to provide a ticket for the method '<Name>'." enthalten.
Tracelinks: StRS-002, SwRS-022, SwRS-026, SwRS-027
Konsolidierung: Kandidat: SwRS-026/SwRS-027 (zwei parallele Ticketprüfpfade – WCF-Bridge und ASP.NET-Core-Handler – mit gleicher fachlicher Funktion)
Status: belegt
```
```
ID: SyRS-002
Titel: Zeitliche Begrenzung und Verlängerung des Sitzungstickets
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Sicherheit)
Akteur: Alle Clientanwendungen
Vorbedingung: Ein gültiges Ticket wurde ausgestellt.
Fakt: `TicketBL` definiert `TicketExpireInMinutes = 30` (Standard), `TicketMonitoringConnectorExpireInMinutes = 5` (Monitoring-Konnektoren) und `TicketExpire24HoursInMinutes = 1440` (Anwendungen mit `ExpirationKind.OneDay`). Für `ExpirationKind.FromSettings` gilt `Math.Max(Einstellung TicketReleaseTime, 30)`. `RefreshTicketExpireDate` verlängert das Ticket nur, wenn das neue Ablaufdatum mindestens 5 Minuten nach dem bisherigen liegt; ein Kommentar benennt die daraus folgenden Randfälle. `DeleteExpiredTickets` entfernt abgelaufene Tickets.
Aussage: Das System soll Sitzungstickets nach einer anwendungsabhängigen Frist von 5 Minuten bis 24 Stunden ungültig werden lassen und sie bei Aktivität verlängern, wobei die Verlängerung aus Performanzgründen erst ab 5 Minuten Differenz geschrieben wird.
Ergebnis: Ein inaktives Ticket verfällt spätestens nach der anwendungsspezifischen Frist; ein aktiv genutztes Ticket bleibt gültig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:26-28, 136-164 (`GetExpireDate`) – Begründung: Enthält alle Ablauffristen und deren Zuordnung zu `ExpirationKind`.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:113-134 (`RefreshTicketExpireDate`) – Begründung: Durchgesetzte 5-Minuten-Schreibschwelle.
- [KONTEXT] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:117-127 (Kommentarblock zu den Randfällen) – Begründung: Dokumentiert die bewusst in Kauf genommene Fehlerklasse „Ticket verfällt früher als erwartet" und verweist auf die Retry-Logik der Clients.
Prüfidee: Ticket ausstellen, 31 Minuten ohne Aufruf warten, danach einen Aufruf absetzen; er muss mit `InvalidTicket` abgewiesen werden.
Tracelinks: StRS-002, SwRS-022
Konsolidierung: nein
Status: belegt; Workaround – die 5-Minuten-Schwelle erzeugt laut Codekommentar einen bekannten Randfall vorzeitigen Ticketverfalls
```
```
ID: SyRS-003
Titel: Konfigurierbares Anmeldeverfahren mit Fallback
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Administrator
Vorbedingung: In den Anwendungseinstellungen ist eine `SystemAuthenticationMethod` gesetzt.
Fakt: `AuthenticatorFactory.GetAuthenticatorWithSystemAuth` wählt anhand von `SystemAuthenticationMethod` (`None`, `Basic`, `ActiveDirectory`, `OpenIdConnect`) einen Haupt-Authenticator. Bei `None` entscheidet `WebServiceConfigHelper.Current.ActiveDirectoryAuthEnabled`. Zusätzlich wird pro Benutzer `AppUser.AuthentificationKind` ausgewertet: Bei `CentronLogin` wird ein `FallbackAuthenticator` mit `BasicAuthenticator` als Rückfallebene gebildet; bei `WindowsAuth` bzw. `OpenIdConnectAuth` ein `FailingAuthenticator` mit der Meldung, dass das Verfahren fehlkonfiguriert ist.
Aussage: Das System soll das Anmeldeverfahren systemweit konfigurierbar machen und je Benutzer ein abweichendes, am Benutzerdatensatz hinterlegtes Verfahren berücksichtigen; ist ein benutzerspezifisches Verfahren serverseitig nicht verfügbar, soll die Anmeldung mit einer erklärenden Meldung scheitern statt stillschweigend auf ein schwächeres Verfahren zurückzufallen.
Ergebnis: Benutzer mit `AuthentificationKind = CentronLogin` können sich auch bei aktivem AD/OIDC lokal anmelden; Benutzer mit AD-/OIDC-Bindung erhalten bei fehlender Serverkonfiguration eine Fehlkonfigurationsmeldung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:54-117 – Begründung: Vollständige Verfahrensauswahl inklusive Fallback-Konstruktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:203-207 (`GetAuthenticationKindFromUserName`) – Begründung: Belegt die benutzerindividuelle Verfahrenszuordnung.
- [SEKUNDÄR] `LocalizedStrings.AuthenticatorFactory_FallbackMisconfiguredErrorMessage` (referenziert in AuthenticatorFactory.cs:74, 80) – Begründung: Fachliche Formulierung des Fehlkonfigurationsfalls.
Prüfidee: Benutzer mit `AuthentificationKind = WindowsAuth` bei deaktiviertem Active Directory anmelden; die Anmeldung muss mit der Fehlkonfigurationsmeldung scheitern und nicht per Basic-Anmeldung gelingen.
Tracelinks: StRS-017, SwRS-023
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-004
Titel: Kennwortprüfung des lokalen Benutzerstamms
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Anmeldeverfahren `Basic` bzw. Fallback auf `BasicAuthenticator`.
Fakt: `BasicAuthenticator.AuthenticateInternal` berechnet `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` und sucht einen `AppUser` mit `Name == UserName && Password == decodedPassword`. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. Leere Benutzername- oder Kennworteingaben werden vorab mit `DefaultMessageCodes.NoUsernameOrPassword` abgewiesen. Jeder Versuch wird über NLog protokolliert (`Logger.Info` bei Erfolg, `Logger.Warn` bei Fehlschlag, jeweils mit `RequestId`, Benutzername und Kontext).
Aussage: Das System soll Kennwörter des lokalen Benutzerstamms als SHA-1-Hashwert speichern und vergleichen; da kein benutzerindividueller Zufallswert (Salt) verwendet wird, ist dieses Verfahren nach heutigem Stand nicht ausreichend und in der Zielarchitektur zu ersetzen.
Ergebnis: Bei Übereinstimmung von Benutzername und Kennworthash wird der Benutzer authentifiziert, andernfalls mit `DefaultMessageCodes.LoginFailed` abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50 – Begründung: Zeigt Hashverfahren, fehlenden Salt und den Datenbankvergleich unmittelbar im durchgesetzten Anmeldepfad.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:37-43 – Begründung: Durchgesetzte Vorabprüfung auf leere Anmeldedaten.
- [KONTEXT] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:48 (`// TODO the password should be salted!!!`) – Begründung: Das Entwicklungsteam kennzeichnet die Implementierung selbst als unzureichend.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:477-483 (`HashToken` mit `SHA256`) – Begründung: Gegenbeleg – im neueren Access-Token-Modul wird bereits SHA-256 verwendet; die Schwäche betrifft ausschließlich den Altpfad der Benutzerkennwörter.
Prüfidee: Zwei Benutzer mit identischem Kennwort anlegen; in der Tabelle `Sichbenu` müssen beide denselben `Password`-Wert tragen. Genau dieses Verhalten muss im Zielsystem ausgeschlossen sein.
Tracelinks: StRS-017, SwRS-024
Konsolidierung: Kandidat: SwRS-024 (zwei unterschiedliche Hashverfahren für dieselbe fachliche Funktion „Geheimnis prüfen"; Vereinheitlichung auf ein modernes Verfahren erforderlich)
Status: belegt; Workaround – ungesalzenes SHA-1, laut Quelltextkommentar bekannte Altlast; in der Migration mit hoher Priorität zu ersetzen
```
```
ID: SyRS-005
Titel: Deaktivierung von Benutzerkonten über mehrere unabhängige Kriterien
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer
Vorbedingung: Ein Benutzerdatensatz existiert.
Fakt: `Authenticator.ValidateAppUser` verweigert die Anmeldung, wenn (a) `AppUser.IsAccountDisabled` gesetzt ist, (b) das heutige Datum im Sperrzeitraum `AccountDisabledFromDate`/`AccountDisabledToDate` liegt oder (c) `EmployeeBL.IsActiveEmployeeCompact(user.Employee)` fehlschlägt (Prüfung auf Einstellungs- und Austrittstermin). In allen drei Fällen wird `DefaultMessageCodes.EmployeeAccountDeactivated` mit der Meldung „Mitarbeiterkonto wurde deaktiviert" zurückgegeben; der konkrete Grund wird ausschließlich ins Log geschrieben.
Aussage: Das System soll ein Benutzerkonto sperren, sobald es manuell deaktiviert wurde, sich in einem hinterlegten Sperrzeitraum befindet oder der zugehörige Mitarbeiter nach Einstellungs-/Austrittsdatum nicht aktiv ist, und dem Anmeldenden dabei keine Auskunft über den konkreten Sperrgrund geben.
Ergebnis: Anmeldung wird abgewiesen; das Serverlog enthält den auslösenden Grund.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:157-218 (`ValidateAppUser`) – Begründung: Enthält alle drei Sperrkriterien und die einheitliche, nicht auskunftsgebende Fehlermeldung.
- [SEKUNDÄR] `LocalizedStrings.UsersBL_AuthenticateAppUser_MitarbeiterKontoWurdeDeaktiviert` – Begründung: Einheitlicher Meldungstext für alle Sperrgründe.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:176-177 (Logtext „…deactivated through the checkbox 'User hat Account in c-entron'") – Begründung: Benennt das zugehörige UI-Element und damit die fachliche Bedienung.
Prüfidee: Mitarbeiter mit Austrittstermin in der Vergangenheit anlegen; die Anmeldung muss mit `EmployeeAccountDeactivated` scheitern, obwohl das Konto nicht manuell deaktiviert wurde.
Tracelinks: StRS-002, StRS-017
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-006
Titel: Zwei-Faktor-Authentifizierung über RADIUS oder E-Mail
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: `TwoFactorAuthEnabled = true` in der Web-Service-Konfiguration.
Fakt: Nach erfolgreicher Kennwortprüfung ruft `BasicAuthenticator` zwingend `TwoFactorAuthBL.ValidateTwoFactor(userName, password, loggedInUser, applicationName, machineName)` auf; schlägt dies fehl, wird mit `DefaultMessageCodes.TwoFactorAuthFailed` abgewiesen. Es existieren die Validierer `RadiusTwoFactorValidator` (mit eigenem `RadiusClient` und `RadiusPaketParser`) und `EmailTwoFactorValidator` hinter der Schnittstelle `ITwoFactorValidator`. Konfigurierbar sind `TwoFactorAuthType` (Standard `RadiusServer`), `RadiusServerAddress`, `RadiusServerSecret` (verschlüsselt abgelegt), `RadiusServerConnectionTimeoutInSeconds` (Standard 30), `MailTwoFactorAuthTimeoutInSeconds` (Standard 120) und `TwoFactorValidDurationInDays`.
Aussage: Das System soll bei aktivierter Zwei-Faktor-Authentifizierung nach erfolgreicher Kennwortprüfung einen zweiten Faktor über einen RADIUS-Server oder per E-Mail-Einmalcode prüfen und die Anmeldung ohne diesen Faktor verweigern.
Ergebnis: Nur Anmeldungen mit bestandenem zweiten Faktor erhalten ein Ticket; die Gültigkeit des zweiten Faktors kann für eine konfigurierbare Anzahl Tage bestehen bleiben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 – Begründung: Der zweite Faktor ist nicht optional umgehbar, sondern Teil des Anmeldepfads.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/ (`ITwoFactorValidator`, `RadiusTwoFactorValidator`, `EmailTwoFactorValidator`, `RadiusClient`, `RadiusPaketParser`, `TwoFactorAuthBL`) – Begründung: Beide Verfahren sind vollständig implementiert.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:23-32 – Begründung: Konfigurationsschalter und Zeitgrenzen.
Prüfidee: Mail-2FA aktivieren und den Einmalcode 121 Sekunden nach Anforderung eingeben; die Anmeldung muss wegen Zeitablaufs scheitern.
Tracelinks: StRS-017, SyRS-003
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-007
Titel: Lizenz- und Kontingentprüfung bei der Anmeldung
Ebene: SyRS
Typ: Sicherheit / funktional
Akteur: Alle Clientanwendungen, Lizenzgeber
Vorbedingung: Der Benutzer wurde erfolgreich authentifiziert.
Fakt: `Authenticator.AuthenticateUser` gibt ein bereits bestehendes Ticket für dieselbe Kombination aus Anwendung, Benutzer, Web-Account und Gerät unverändert zurück, ohne Lizenz zu verbrauchen. Erst wenn kein Ticket existiert, ruft es `LicenseManager.CheckLicense(applicationKind, appVersion, user)`. Dort wird je Lizenz-GUID geprüft: Versionsgültigkeit (`CheckLicenseVersion`) und, falls ein Benutzer übergeben wurde, ob `TicketBL.GetTicketCount(license, app.LicenseUsageKind, user) >= GetLicenseCount(license)`; in diesem Fall wird `DefaultMessageCodes.LicenseMaximumReached` mit der Meldung „Die maximale Anzahl an Lizenzen wurde erreicht." gemeldet. Die Zählweise unterscheidet `LicenseUsageKind.PerUser` und `PerUserAndPerMachine`.
Aussage: Das System soll die Anzahl gleichzeitiger Anmeldungen je Produkt gegen das Lizenzkontingent prüfen und bestehende Sitzungen desselben Benutzers auf demselben Gerät nicht erneut auf das Kontingent anrechnen.
Ergebnis: Bei erschöpftem Kontingent erhält der Anmeldende die Lizenzmeldung; bestehende Sitzungen bleiben unberührt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:124-142 – Begründung: Zeigt die Reihenfolge „bestehendes Ticket vor Lizenzprüfung" und die Serialisierung über `lock`.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:270-302 (`CheckLicense`) – Begründung: Enthält Versions- und Kontingentprüfung sowie das Verhalten bei mehreren zulässigen Lizenz-GUIDs (Erfolg genügt bei einer).
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:45,53 (`licenseUsageKind: LicenseUsageKind.PerUser` für Service-Board) – Begründung: Belegt die produktabhängige Zählweise.
Prüfidee: Lizenz mit `count = 1` einspielen und von zwei verschiedenen Geräten anmelden; die zweite Anmeldung muss `LicenseMaximumReached` liefern, die Wiederanmeldung vom ersten Gerät hingegen gelingen.
Tracelinks: StRS-004, SwRS-020, SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-008
Titel: Anwendungsbezogene Rechte- und Sperrprüfung beim Login
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Systemintegrator
Vorbedingung: Der Benutzer ist authentifiziert und die aufrufende Anwendung ist über ihre Lizenz-GUID erkannt.
Fakt: `Authenticator.ValidateRights(applicationKind, user)` verweigert die Ticketausstellung, wenn die Anwendung ein `DisallowingRight` definiert und der Benutzer dieses besitzt, oder wenn sie ein `RequiredRight` definiert und der Benutzer dieses nicht besitzt. Beispiele: `ServiceBoard` und `ServiceBoardNext` mit `disallowingRight: RIGHT_DISALLOW_SERVICEBOARD_LOGIN (20800073)`; `RiversuiteInventory`, `RiversuitePro` und `RiversuiteOnline` mit `requiredRight`; `MailScannerNET` mit `requiredRight: ACCESS_VMA_MODULE (20800112)`.
Aussage: Das System soll für einzelne Clientanwendungen den Zugang zusätzlich über ein erforderliches oder ein ausschließendes Benutzerrecht steuern, unabhängig von der Lizenz.
Ergebnis: Der Anmeldeversuch wird mit `DefaultMessageCodes.RightCheckFailed` und dem Anwendungsnamen abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:68-86 (`ValidateRights`) – Begründung: Durchgesetzte Prüfung vor der Ticketvergabe.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:28,34,36,41,44,45,53,58-61 – Begründung: Konkrete Zuordnung der Rechte-IDs zu Anwendungen; die IDs sind bewusst als lokale Konstanten dupliziert („// Taken from UserRightsConst").
Prüfidee: Benutzer das Recht 20800073 zuweisen und Anmeldung am Service-Board versuchen; die Anmeldung muss mit `RightCheckFailed` scheitern.
Tracelinks: StRS-002, StRS-004, SwRS-020
Konsolidierung: Kandidat: SwRS-018 (Rechte-IDs sind in `ApplicationKind.cs` dupliziert statt aus `UserRightsConst` referenziert)
Status: belegt; Workaround – vier Rechte-IDs sind als lokale Konstanten kopiert und laufen bei Änderungen auseinander
```
```
ID: SyRS-009
Titel: API-Zugriff über persönliche Access Tokens
Ebene: SyRS
Typ: Schnittstelle / Sicherheit
Akteur: API-Client (technisch)
Vorbedingung: Die Lizenz `LicenseGuids.AccessTokenModule` liegt vor; ein Token wurde für einen Mitarbeiter ausgestellt.
Fakt: `AccessTokenBL.CreatePersonalToken` erzeugt einen Zufallstoken, speichert ausschließlich dessen SHA-256-Hash (`TokenHash`) und gibt den Klartext genau einmal zurück („only available once during creation"). `ValidateToken(plainToken, ipAddress, apiMethod)` prüft Lizenz, Hashübereinstimmung, `IsActive` und schreibt einen Eintrag über `AccessTokenLogBL`. Tokens besitzen ein optionales Ablaufdatum (`ExpiresAt`) und werden logisch gelöscht (`IsDeleted`). Die Anzahl aktiver, nicht abgelaufener Tokens ist gegen die Lizenzanzahl begrenzt. Im `AuthenticateInterceptor` unterliegen Access Tokens ausdrücklich keiner Anwendungsbeschränkung.
Aussage: Das System soll Maschinen-zu-Maschinen-Zugriffe über persönliche, lizenzpflichtige Access Tokens zulassen, deren Klartext nur bei der Erstellung sichtbar ist und deren Verwendung protokolliert wird.
Ergebnis: Ein gültiger Token authentifiziert den Aufruf; jede Verwendung erzeugt einen Logeintrag mit IP-Adresse und aufgerufener Methode.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:154-186 (Erzeugung, Hashbildung, Kollisionsbehandlung) – Begründung: Belegt die Einweg-Speicherung des Geheimnisses.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:377-400, 477-483 (`ValidateToken`, `HashToken` mit SHA-256) – Begründung: Prüf- und Hashverfahren.
- [PRIMÄR] src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:436-451 (Kontingentprüfung gegen Lizenzanzahl) – Begründung: Lizenzgebundene Mengenbegrenzung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:51-58 (Kommentar „Access tokens don't have application restrictions") – Begründung: Belegt die abweichende, weniger restriktive Prüfung gegenüber Tickets.
Prüfidee: Token erzeugen, Klartext notieren, Detailansicht erneut öffnen; der Klartext darf nicht erneut abrufbar sein. Token deaktivieren und einen API-Aufruf absetzen; er muss abgewiesen werden.
Tracelinks: StRS-004, SwRS-024, SwRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-010
Titel: Methodenbezogene Anwendungsbeschränkung von Web-Service-Aufrufen
Ebene: SyRS
Typ: Sicherheit
Akteur: Systemintegrator, Clientanwendungen
Vorbedingung: Der Aufruf erfolgt mit gültigem Ticket.
Fakt: `AuthenticateInterceptor` liest das `AuthenticateAttribute` der aufgerufenen Methode aus. Ist `attribute.Applications` nicht leer und die Anwendung des Tickets nicht enthalten, wird der Aufruf mit `StatusCode.Failed` und der Meldung „You don't have the permission to execute the method '<Name>'." abgewiesen. Ist das Ticket an einen Web-Account gebunden und `attribute.AllowWebAccountLogin == false`, wird ebenfalls abgewiesen. Ein Quelltextkommentar hält fest, dass die Umkehrung („diese Anwendung darf nur diese Methoden aufrufen") nicht abgedeckt ist.
Aussage: Das System soll je Web-Service-Methode einschränken können, welche Clientanwendungen sie aufrufen dürfen und ob Web-Account-Anmeldungen zugelassen sind.
Ergebnis: Nicht zugelassene Anwendungen und Web-Accounts erhalten eine Berechtigungsfehlermeldung, ohne dass die Methode ausgeführt wird.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:29-48 – Begründung: Durchgesetzte Prüfung vor `invocation.Proceed()`.
- [KONTEXT] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:33-37 (deutscher Kommentar zur Lücke) – Begründung: Das Entwicklungsteam benennt die fehlende Gegenrichtung explizit als bekannte Einschränkung.
Prüfidee: Methode mit `AuthenticateAttribute(Applications = [ApplicationKind.Centron])` mit einem Service-Board-Ticket aufrufen; der Aufruf muss abgewiesen werden.
Tracelinks: SyRS-001, StRS-003, SwRS-027
Konsolidierung: nein
Status: belegt; Workaround – laut Codekommentar deckt der Mechanismus nur eine Richtung ab (Methode schränkt Anwendungen ein, nicht Anwendung schränkt Methoden ein)
```
---
## 2. Berechtigungen
```
ID: SyRS-011
Titel: Auflösung von Benutzerrechten über Gruppenzugehörigkeit
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Der Benutzer ist authentifiziert.
Fakt: `AppRightsBL.HasUserRight(appUserI3D, rightID)` ermittelt die Rechte über den Sitzungs-Cache-Schlüssel `AllRightsFromAppUser{appUserI3D}` und die Abfrage `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `CheckRightsFromUser(appUserI3D, rightI3Ds)` liefert die Schnittmenge einer übergebenen Rechteliste. Rechteänderungen werden in `AppRightLog` mit Kind, Objekt, Beschreibung, Urheber, Zeitpunkt und Anwendungsversion protokolliert.
Aussage: Das System soll das Vorliegen eines Rechts ausschließlich über die Gruppenmitgliedschaft des Benutzers bestimmen und das Ergebnis je Sitzung zwischenspeichern.
Ergebnis: Rechteprüfungen liefern innerhalb einer Sitzung konsistente Ergebnisse; Änderungen an Rechten wirken erst in der Folgesitzung bzw. nach Cache-Invalidierung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:644-664 – Begründung: Enthält Cache-Schlüssel und die maßgebliche SQL-Abfrage.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:95-111 (`CheckRightsFromUser`) – Begründung: Zweiter, ungecachter Prüfpfad für Rechtelisten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-781 (`WriteBaseLog`) – Begründung: Audit aller Rechteänderungen.
Prüfidee: Innerhalb einer laufenden Sitzung ein Recht entziehen; die Prüfung muss bis zum Sitzungsende weiterhin `true` liefern und erst nach Neuanmeldung `false`. Dieses Verhalten ist im Zielsystem bewusst zu bestätigen oder zu ändern.
Tracelinks: StRS-002, SwRS-016, SwRS-017
Konsolidierung: Kandidat: SyRS-013 (identische fachliche Funktion für Web-Accounts über `WebAccountsRights`)
Status: belegt
```
```
ID: SyRS-012
Titel: Einschränkende Rechte „nur eigene" und „nur eigene Filiale"
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Der Benutzer besitzt das Basisrecht für die betreffende Objektart.
Fakt: Zusätzlich zu jedem Basisrecht existieren einschränkende Rechte, deren Besitz den Zugriff *verkleinert*, z. B. `SHOW_OFFERS_ONLY_OWN (20400149)`, `SHOW_OFFERS_ONLY_OWN_BRANCH (20400150)`, `CREATE_NEW_OFFER_ONLY_OWN_BRANCH (20400211)`, `EDIT_OFFER_ONLY_OWN_BRANCH (20800028)`, analog für alle sieben Kundenbelegarten. `HelpdeskBL.GetShowHelpdeskRight` bildet daraus die Stufen `All`, `OnlyOwnBranch`, `OnlyOwn`, `OnlyOwnAndNotify`, `None`. `ReceiptBL.CanUserEditReceipt` und `CanUserCreateReceiptsInBranch` setzen die Filialbeschränkung durch; `BranchBL.IsBranchEqual` behandelt „keine Filiale" und Filial-ID 0 als gleichwertig.
Aussage: Das System soll den Datenzugriff über einschränkende Rechte auf die eigenen Datensätze oder die eigene Filiale begrenzen, wobei der Besitz eines einschränkenden Rechts die Wirkung des Basisrechts reduziert.
Ergebnis: Ein Benutzer mit einschränkendem Recht sieht bzw. bearbeitet ausschließlich die zugelassene Teilmenge und erhält andernfalls `RightCheckFailed`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295 (`CanUserEditReceipt`) – Begründung: Durchgesetzte Zweistufenprüfung Basisrecht + Filialbeschränkung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10270 (`CanUserCreateReceiptsInBranch`) – Begründung: Behandlung von Standardfiliale (null bzw. 0) als Sonderfall.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:255-291 (`ShowHelpdeskRight`-Ableitung) – Begründung: Vollständige Stufenlogik für Tickets.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2192-2213 (Offer-Rechteblock) – Begründung: Belegt das Muster Basisrecht + zwei Einschränkungsrechte je Belegart.
- [KONTEXT] CentronRights.md:9-17 („This is a **restricting right**.") – Begründung: Dokumentiert die invertierte Semantik ausdrücklich.
Prüfidee: Benutzer aus Filiale A mit `EDIT_OFFER` und `EDIT_OFFER_ONLY_OWN_BRANCH` versucht, ein Angebot der Filiale B zu speichern; die Aktion muss mit „Der Benutzer hat nicht das Recht Belege vom Typ \"Angebot\" einer anderen Filiale zu bearbeiten." scheitern.
Tracelinks: StRS-001, StRS-002, SwRS-015
Konsolidierung: Kandidat: Das Muster „Basisrecht + ONLY_OWN + ONLY_OWN_BRANCH" ist für sieben Belegarten, Tickets, Kalender, CRM-Projekte und Projektverwaltung nahezu identisch dupliziert; im Zielsystem als generisches Sichtbarkeitskonzept zusammenführbar.
Status: belegt
```
```
ID: SyRS-013
Titel: Getrenntes Rechtemodell für Web-Accounts
Ebene: SyRS
Typ: Sicherheit
Akteur: Web-Account
Vorbedingung: Der Web-Account ist authentifiziert.
Fakt: `AppRightsBL.HasWebAccountRight` und `GetAllWebRightsFromWebAccount` werten `SELECT WebRightsI3D FROM WebAccountsRights WHERE WebAccountsI3D = :WebAccountI3D` aus; der Cache-Schlüssel lautet `AllRightsFromWebAccount{I3D}`. `HelpdeskBL.CheckRights` verzweigt anhand von `LoggedInUser.IsWebAccountLogin` in `CheckWebRights` statt `CheckUserRigths` und prüft dort z. B. `WEBRIGHT_CREATEREQUEST`. Der Rechte-Nummernraum (11000–61007) ist disjunkt zum Mitarbeiterrechteraum.
Aussage: Das System soll für Web-Accounts ein eigenständiges Rechtemodell führen und bei jeder rechtebewehrten Operation anhand der Anmeldeart zwischen Mitarbeiter- und Web-Account-Rechten unterscheiden.
Ergebnis: Ein Web-Account kann ausschließlich die über `WebAccountsRights` freigegebenen Funktionen ausführen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:666-691 – Begründung: Getrennte Auswertung inkl. eigenem Cache.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-416, 468-474 – Begründung: Verzweigung nach Anmeldeart im Speicherpfad eines Tickets.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/WebAccountRightsConst.cs:9-79 – Begründung: Vollständiger, disjunkter Rechtekatalog.
Prüfidee: Web-Account ohne `WEBRIGHT_CREATEREQUEST` versucht, ein Ticket anzulegen; die Aktion muss mit „Der User hat nicht das Recht, Helpdesks anzulegen." scheitern.
Tracelinks: StRS-003, SyRS-011, SwRS-041
Konsolidierung: Kandidat: SyRS-011 (zwei strukturell gleiche Rechtemodelle; Zusammenführung zu einem Rollen-/Berechtigungsmodell im Zielsystem prüfen)
Status: belegt
```
---
## 3. Belegverarbeitung
```
ID: SyRS-014
Titel: Belegzustandsmodell mit drei Zuständen
Ebene: SyRS
Typ: Daten / funktional
Akteur: Interner Benutzer
Vorbedingung: Ein Beleg existiert.
Fakt: `ReceiptState` kennt genau drei Werte: `Active = 1` („offen"), `Completed = 2` („abgeschlossen"), `Canceled = 3` („storniert"). Zustandswechsel sind an konkrete fachliche Ereignisse gebunden, u. a.: Zahlungseingang setzt `Completed`, Zahlungsrücknahme setzt `Active`; ein WE-Kalkulationsbeleg im Zustand `Active` wird nach Anwenderbestätigung auf `Completed` gesetzt; ein RMA-Lieferschein ebenso. Ein Beleg im Zustand `Canceled` kann nicht mehr als bezahlt/unbezahlt markiert werden.
Aussage: Das System soll für jeden Beleg genau einen der drei Zustände offen, abgeschlossen oder storniert führen und Zustandsänderungen ausschließlich über definierte fachliche Ereignisse zulassen; stornierte Belege sind fachlich abschließend und dürfen nicht mehr in Zahlungsvorgänge einbezogen werden.
Ergebnis: Der Belegzustand ist zu jedem Zeitpunkt eindeutig; Aktionen auf stornierten Belegen werden mit einer erklärenden Fehlermeldung abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28 – Begründung: Definiert normativ die drei Zustände und ihre deutschen Bezeichnungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4936-4951 – Begründung: Durchgesetzte Sperre für stornierte Belege und der Zustandswechsel bei Zahlung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4130-4180 (`CheckCloseReceipt`, `CheckCloseRMADeliverylistReceipt`) – Begründung: Zwei weitere, an Anwenderbestätigung gekoppelte Übergänge nach `Completed`.
- [SEKUNDÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:18-27 (`GetReceiptStateString`) – Begründung: Anwendersichtbare Zustandsbezeichnungen.
Prüfidee: Rechnung stornieren und anschließend als bezahlt markieren; der Aufruf muss mit „Der Beleg … wurde stoniert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden." scheitern (Schreibfehler im Original beachten).
Tracelinks: StRS-005, StRS-020, StRS-023, SwRS-012
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-015
Titel: Belegnummernvergabe aus filial- und mandantenbezogenen Nummernkreisen
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer, System
Vorbedingung: Für die Belegart und die Filiale des Belegs existiert ein `NumberGroup`-Datensatz.
Fakt: `NumberGroupEnum` definiert 31 Nummernkreise; jeder ist über `GetTableName()`/`GetFieldName()` fest an eine Tabelle und Spalte gebunden (z. B. `Invoice` → `RechKopf.Nummer`, `Helpdesk` → `hlpdsk_requests.Nummer`, `ArticleCode` → `Artik.ArtikelCode` mit Stringvergleich). `NumberGroupBL.FindNextNumber` bildet `current + interval` und erhöht so lange um `interval`, bis die Nummer in der Zieltabelle nachweislich nicht vergeben ist; für `Customer` und `Supplier` wird zusätzlich gegen `dbo.Kunden` bzw. `dbo.Kreditor` geprüft. `ReceiptBL.UpdateReceiptNumber` wählt den Nummernkreis der Belegfiliale, falls `BranchI3D > 0`, sonst den Mandanten-Nummernkreis.
Aussage: Das System soll Belegnummern je Belegart, Mandant und Filiale aus einem konfigurierbaren Nummernkreis mit Startwert, Intervall und Bereichsgrenzen vergeben und dabei sicherstellen, dass keine bereits vergebene Nummer erneut ausgegeben wird.
Ergebnis: Jede vergebene Nummer ist innerhalb ihrer Zieltabelle eindeutig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:94-134 (`FindNextNumber`) – Begründung: Enthält die durchgesetzte Kollisionsprüfung gegen die Zieltabelle.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:76-197 (`GetTableName`, `GetFieldName`, `GetCompareAsStrings`) – Begründung: Vollständige Zuordnung Nummernkreis → Tabelle/Spalte.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7265-7285 (`UpdateReceiptNumber`) – Begründung: Filial- bzw. mandantenbezogene Auswahl des Nummernkreises.
Prüfidee: In `RechKopf` manuell eine Rechnung mit der nächsten erwarteten Nummer anlegen und anschließend eine Rechnung im System erzeugen; die vergebene Nummer muss die manuell belegte überspringen.
Tracelinks: StRS-001, StRS-005, StRS-006, SwRS-010, SwRS-011
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-016
Titel: Versionierung von Belegen
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer
Vorbedingung: Der Beleg wurde bereits gespeichert.
Fakt: `ReceiptBase.Version` führt eine fortlaufende Versionsnummer. `ReceiptBL.SaveReceipt` akzeptiert nur drei Fälle: erste Version (kein Vorgänger und `Version == 1`), unveränderte Version (`Version == previous.Version`) oder Folgeversion (`Version == previous.Version + 1`); andernfalls bricht der Speichervorgang mit „Der Beleg hat keine gültige Versionsnummer." ab. Bei einer neuen Version wird zuvor `CanUserEditReceipt` geprüft und anschließend `SaveReceiptVersion(receipt, previousReceiptVersion)` ausgeführt; für Belege, die Kundenaktivitäten erzeugen, wird zusätzlich eine Aktivität angelegt.
Aussage: Das System soll fachlich relevante Belegänderungen als neue, lückenlos aufsteigende Belegversion führen und den Vorzustand vollständig archivieren; das Überspringen oder Zurücksetzen von Versionsnummern soll abgewiesen werden.
Ergebnis: Versionsnummern sind je Beleg lückenlos aufsteigend; zu jeder Vorversion existiert ein vollständiger Archivsatz.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578 – Begründung: Explizite, durchgesetzte Versionsnummernvalidierung mit drei zulässigen Fällen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3621-3634 – Begründung: Kopplung von Versionsanlage, Rechteprüfung und Archivierung.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 – Begründung: Beschreibt die Versionstabellen als exakte 1:1-Kopien inklusive `OriginalI3D` und `KopfVersionsI3D`.
Prüfidee: Beleg mit `Version = previous.Version + 2` speichern; der Aufruf muss mit „Der Beleg hat keine gültige Versionsnummer." scheitern.
Tracelinks: StRS-015, SwRS-007, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-017
Titel: Schutz vor konkurrierenden Belegänderungen
Ebene: SyRS
Typ: funktional / nicht-funktional (ISO 25010: Zuverlässigkeit)
Akteur: Interner Benutzer
Vorbedingung: Zwei Benutzer bearbeiten denselben Beleg.
Fakt: Es existieren zwei Mechanismen. (a) Optimistisch: `ReceiptBase.ConcurrencyControlGuid` (Datenbankspalte `GUI3D`) wird in mindestens acht Änderungsmethoden gegen den vom Client übergebenen Wert geprüft; bei Abweichung wird `DefaultMessageCodes.ChangedByOtherInstance` mit „The receipt {I3D} ({Kind}) was changed in the meantime." zurückgegeben. (b) Pessimistisch: `TryLockReceipt`/`UnLockReceipt` sperren einen Beleg für andere Benutzer; beim Anlegen wird bei `autoLockIfNewReceipt = true` automatisch gesperrt.
Aussage: Das System soll konkurrierende Änderungen an demselben Beleg verhindern, indem es den Beleg während der Bearbeitung für andere Benutzer sperrt und zusätzlich beim Schreiben prüft, ob der Beleg zwischenzeitlich verändert wurde.
Ergebnis: Die zweite konkurrierende Änderung wird abgewiesen; der Benutzer erhält den Hinweis auf die zwischenzeitliche Änderung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4808-4809, 4843-4844, 4884-4885, 4939-4940, 4988-4989, 5039-5040, 5272 – Begründung: Sieben Fundstellen derselben optimistischen Prüfung belegen deren systematische Anwendung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3087-3093, 3166-3174, 3915-3917 (`TryLockReceipt`, `UnLockReceipt`) – Begründung: Pessimistische Sperre inkl. automatischer Sperre bei Neuanlage.
- [SEKUNDÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptSearch/*ReceiptSearchConfiguration.cs (`ConcurrencyControlGuid = AK.GUI3D`) – Begründung: Belegt die Abbildung auf die Datenbankspalte `GUI3D` für alle Belegarten.
Prüfidee: Beleg in zwei Sitzungen laden, in Sitzung 1 speichern, danach in Sitzung 2 speichern; der zweite Speichervorgang muss `ChangedByOtherInstance` liefern.
Tracelinks: StRS-015, SwRS-004
Konsolidierung: Kandidat: Die identische GUID-Prüfung ist an sieben Stellen kopiert statt zentral gekapselt.
Status: belegt
```
```
ID: SyRS-018
Titel: Rechteprüfung beim Anlegen und Bearbeiten von Belegen
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer
Vorbedingung: Ein Beleg soll gespeichert werden.
Fakt: `ReceiptBL.SaveReceipt` prüft bei neuen Belegen `CanUserCreateNewReceiptsAtCustomerOrSupplier` und `CanUserCreateReceiptsInBranch`, bei neuen Versionen `CanUserEditReceipt`. Jede Prüfung erfolgt innerhalb der umschließenden Transaktion und bricht den gesamten Speichervorgang ab. Die Rechte-IDs stammen belegartspezifisch aus `SpecificLogics` (`HasRightToCreateANewReceiptOnlyOwnBranch`, `HasRightToEditReceipt`, `HasRightToEditReceiptOnlyOwnBranch`, `HasRightToViewReceipt`).
Aussage: Das System soll die Berechtigung zum Anlegen und Ändern eines Belegs serverseitig innerhalb der Speichertransaktion prüfen und den Vorgang bei fehlender Berechtigung vollständig zurückweisen.
Ergebnis: Kein Beleg und keine Belegversion wird persistiert, wenn die Berechtigung fehlt; es entsteht keine Teiländerung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3600-3634 – Begründung: Zeigt die Rechteprüfungen innerhalb von `Session.WithTransaction`.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3544 (`return this.Session.WithTransaction(() => …)`) – Begründung: Belegt die transaktionale Klammer des gesamten Speichervorgangs.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10311 – Begründung: Implementierung der drei Prüfmethoden.
Prüfidee: Benutzer ohne `CREATE_NEW_INVOICE` legt eine Rechnung an; nach dem Fehlschlag darf in `RechKopf` kein neuer Datensatz und in der Nummernkreistabelle keine erhöhte `Current`-Nummer stehen.
Tracelinks: StRS-002, StRS-005, SyRS-012, SwRS-015
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-019
Titel: Automatische Lagerbuchung bei Belegspeicherung
Ebene: SyRS
Typ: funktional
Akteur: System, Interner Benutzer
Vorbedingung: Der Beleg enthält Artikelpositionen mit `ChangeStock = true`.
Fakt: `ReceiptArticleBookingBL.BookArticlesForItem` bucht nur für die Positionsarten `Article`, `CustomerDiscount`, `SupplierFreightNoSplitArticle`, `SupplierInsuranceNoSplitArticle`. Positionen mit `OnlyPriceValue = true` werden übersprungen. Die zu buchende Menge ist die Differenz `(QuantityComplete − QuantityProcessed)` gegenüber dem Vorzustand derselben Position **im selben Lager**; bei Lagerwechsel wird der Vorzustand nicht angerechnet. Ist die Differenz 0, erfolgt keine Buchung. `UnBookArticles` storniert Buchungen für entfernte Positionen, gewechselte Lager und auf `false` gesetztes `ChangeStock`.
Aussage: Das System soll den Lagerbestand bei jeder Belegspeicherung um die Mengendifferenz gegenüber der Vorversion fortschreiben, wobei ein Lagerwechsel als vollständige Aus- und Einbuchung behandelt wird.
Ergebnis: Der Lagerbestand ist nach dem Speichern konsistent mit den Positionsmengen des Belegs; entfernte Positionen sind vollständig ausgebucht.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:171-236 – Begründung: Enthält die vollständige Buchungsregel inklusive Ausschlusskriterien.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:97-123 (`UnBookArticles`) – Begründung: Definiert die drei Stornierungsauslöser.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:180-184 (Kommentar zu `OnlyPriceValue`) – Begründung: Erläutert einen nicht selbsterklärenden Sonderfall bei Gutschriften.
Prüfidee: Position eines gespeicherten Lieferscheins vom Hauptlager auf ein Nebenlager umstellen; das Hauptlager muss die volle Menge zurückerhalten und das Nebenlager die volle Menge abgeben.
Tracelinks: StRS-010, SwRS-030, SwRS-031
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-020
Titel: Datumsabhängige Ermittlung des Mehrwertsteuersatzes
Ebene: SyRS
Typ: funktional
Akteur: System
Vorbedingung: Für den Artikel bzw. die Position ist ein Steuersatz hinterlegt; Steuersätze bilden über `NextTaxRate` eine Kette.
Fakt: `TaxBL.GetTaxRateForReceiptItem(taxRateI3D, receiptDate, articleI3D)` läuft die `NextTaxRate`-Kette bis zum Ende vor und danach rückwärts, solange der Vorgängersatz ein Ablaufdatum besitzt, dessen Datumsanteil `>= receiptDate.Date` ist. Fehlt der Steuersatz, greift die Fallbackkette Artikel → Sekundär-Warengruppe → Warengruppe → Standardsatz des Standardlands. Existieren mehrere Steuersätze mit demselben Folgesatz, wird eine `ResultException` mit ausführlichem deutschem Erklärungstext geworfen.
Aussage: Das System soll den auf eine Belegposition anzuwendenden Mehrwertsteuersatz aus dem Belegdatum und einer als einfache Kette modellierten Steuersatzhistorie bestimmen und eine mehrdeutige Kette als Konfigurationsfehler ablehnen.
Ergebnis: Belege mit historischem Datum werden mit dem damals gültigen Satz berechnet; mehrdeutige Steuersatzketten führen zu einer erklärenden Fehlermeldung statt zu einer stillen Fehlberechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237 (`GetTaxRateForReceiptItem`) – Begründung: Vollständiger, durchgesetzter Ermittlungsalgorithmus.
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:239-284 (`GetDefaultTaxtRateByArticle`, `GetDefaultTaxtRateByCountry`) – Begründung: Definiert die Fallbackreihenfolge.
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:286-320 (`GetPreviousTaxRate` mit `ResultException` bei Mehrdeutigkeit) – Begründung: Durchgesetzte Konsistenzprüfung der Steuersatzkette.
- [SEKUNDÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:302-315 (deutscher Erklärungstext) – Begründung: Fachliche Formulierung der Anforderung an die Steuersatzpflege.
Prüfidee: Steuersatz 16 % mit Ablaufdatum 31.12.2020 und Folgesatz 19 % anlegen; eine Rechnung mit Datum 01.12.2020 muss 16 %, eine mit Datum 01.02.2021 muss 19 % verwenden.
Tracelinks: StRS-005, StRS-011, SwRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-021
Titel: Vorrangfolge der Preisfindung
Ebene: SyRS
Typ: funktional
Akteur: System
Vorbedingung: Eine Artikelposition wird in einen Beleg eingefügt oder neu bewertet.
Fakt: `ReceiptItemPriceBL` prüft zuerst `GetContractSpecialPrice(article, contractI3D)`; nur wenn kein Vertragssonderpreis vorliegt, wird `GetSpecialPrice(article, customer)` ausgewertet; Staffelpreise (`ArticleVolumePrices`) greifen nachrangig und nur, wenn `UseVolumePrice(contractI3D)` wahr ist. Beide Sonderpreisarten unterscheiden fünf Änderungsarten (Festpreis, Aufschlag auf EK, Abschlag auf UVP, Abschlag auf VK, Abschlag auf Listenpreis) und zwei Änderungsmodi (absolut, prozentual). Vertragswerte sind vorzeichenverkehrt hinterlegt.
Aussage: Das System soll den Verkaufspreis einer Position nach der festen Vorrangfolge Vertragssonderpreis vor Kundensonderpreis vor Mengenstaffel ermitteln.
Ergebnis: Der Positionspreis ist bei gegebenem Artikel, Kunde, Vertrag und Menge deterministisch reproduzierbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266 – Begründung: Enthält die durchgesetzte Vorrangfolge als `if/else`-Kaskade.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:181,187,192 (Kommentare „The contract values are inverted") – Begründung: Weist eine migrationskritische Datenkonvention aus.
Prüfidee: Siehe StRS-025.
Tracelinks: StRS-025, SwRS-029
Konsolidierung: Kandidat: SwRS-029
Status: belegt
```
```
ID: SyRS-022
Titel: Selektion fälliger Verträge für den Abrechnungslauf
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer (Vertragsverwaltung)
Vorbedingung: Verträge sind mit Abrechnungsparametern angelegt.
Fakt: `AutomaticFacturaBL.GetActiveContracts` filtert ausschließlich Verträge mit `State == 1` und wertet je nach Modus aus: Anzeigemodus (`IsActiveOnly`) auf Basis von `ContractBegin`/`ContractEnd`/`AutomatedProlongation`; Abrechnungsmodus auf Basis von `CalculationKind`, `LastPaidDate`, `FirstPaidDate` und Stichtag. Anschließend entfernt `SearchBillingContracts` (a) dynamische Bedarfsverträge ohne Sonderartikel, (b) Verträge, die zu einer leeren Rechnung führen würden. Verträge mit fehlenden Stückzahlen, seriennummernpflichtigen oder nicht lieferbaren Artikeln werden markiert (`WithEmptyPos`, `WithBarcode`, `NoDeliverable`).
Aussage: Das System soll für einen Abrechnungsstichtag genau die Verträge selektieren, die nach Vertragslaufzeit, Abrechnungsart und letzter Abrechnung fällig sind, und Verträge ausschließen, die zu einer leeren Rechnung führen würden.
Ergebnis: Der Abrechnungslauf erzeugt keine leeren Rechnungen und keine Doppelabrechnung derselben Periode; problematische Verträge werden dem Anwender markiert zur Prüfung vorgelegt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845 – Begründung: Vollständige Selektionsbedingung im Code.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:881-947 – Begründung: Ausschluss- und Markierungsregeln inklusive deutscher Kommentare („leere RE vermeiden", „Verträge ohne Stückanzahl").
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md – Begründung: Beschreibt die Sonderbehandlung von RMM-Artikeln in der Vertragsabrechnung.
Prüfidee: Vertrag ohne abrechenbare Positionen und ohne Sonderartikel anlegen; er darf im Abrechnungslauf nicht erscheinen.
Tracelinks: StRS-007, SwRS-032
Konsolidierung: nein
Status: belegt
```
---
## 4. Schnittstellen
```
ID: SyRS-023
Titel: Erzeugung elektronischer Rechnungen nach konfiguriertem Profil
Ebene: SyRS
Typ: Schnittstelle
Akteur: System, Rechnungsempfänger
Vorbedingung: In den Rechnungseinstellungen ist ein `ZugferdKind` gesetzt oder wird per Migrationsregel abgeleitet.
Fakt: `ReceiptWebServiceBL.GetReceiptInvoiceSettings` liefert `ActiveZugferdInterface`; ist dieser `None`, wird das Profil aus den Altschaltern `IsZugferdXRechnungActive` und `IsXRechung2Active` abgeleitet (`ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2` oder `ZUGFeRD_XInvoice_2_0`). `InvoiceZugferdBL` verwendet als Standard `ZugferdKind.ZUGFeRD_XInvoice_3_0_1` und setzt die passende PDF/A-Version (`PdfZugferdVersion.Version2_0_1` bzw. `Version2_1`), Konformitätsstufe `EN16931` und den Anhangsnamen `factur-x.xml`. Weitere Schalter steuern Archivierung, XML-Anhang an E-Mails, Bevorzugung des Mandantennamens, Unterdrückung von Artikel- und EAN-Code sowie die Wahl des Ansprechpartners (`ZugferdSellerContactPersonKind`, Standard `Ceo`).
Aussage: Das System soll das E-Rechnungsformat aus einer zentralen Einstellung ableiten, dabei ältere Einzelschalter rückwärtskompatibel interpretieren und die formatabhängigen technischen Parameter automatisch setzen.
Ergebnis: Auch bei nicht gesetzter Neueinstellung wird ein gültiges Profil bestimmt; das erzeugte Dokument entspricht diesem Profil.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs:2394-2446 – Begründung: Enthält die vollständige Migrationsregel von Altschaltern auf `ZugferdKind`.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:94, 204-228, 1271-1289 – Begründung: Formatabhängige technische Parameter und Guideline-IDs.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Receipts/Invoices/ZugferdKind.cs:44 (`NewestActiveZugferdVersion`) – Begründung: Zentrale Definition des jeweils aktuellen Profils.
Prüfidee: `ActiveZugferdInterface` leeren und nur `IsZugferdXRechnungActive = true`, `IsXRechung2Active = false` setzen; die Einstellungsabfrage muss `ZUGFeRD_XInvoice_1_2` liefern.
Tracelinks: StRS-011, StRS-012, SwRS-045
Konsolidierung: Kandidat: Drei Einstellungsschalter (`ActiveZugferdInterface`, `IsZugferdXRechnungActive`, `IsXRechung2Active`) bilden dieselbe fachliche Entscheidung ab; im Zielsystem auf einen Schalter zu reduzieren.
Status: belegt; Workaround – die Ableitung aus Altschaltern ist eine Migrationshilfe für historische Konfigurationen
```
```
ID: SyRS-024
Titel: Automatisierter EDI-Import von Lieferantendokumenten
Ebene: SyRS
Typ: Schnittstelle
Akteur: Hintergrunddienst, Distributor
Vorbedingung: Für den Lieferanten existiert eine `SupplierEdiConfigurations`-Konfiguration mit Format, Dokumentart und Verbindungsdaten.
Fakt: Der `EdiDownloadService` startet eine Minute nach dem Dienststart und läuft anschließend alle 30 Minuten. `SupplierEdiBL.ApplyDistriToCentron(xmlData, config, deal)` verteilt die Dateien anhand von `EdiDataType` und `ObjectKind` an die formatspezifischen Lesemethoden und löscht die Dateien nach erfolgreicher Verarbeitung. Verarbeitungszustände werden über `EDILogBL` mit den Zuständen `DownloadOK`, `DownloadError`, `DownloadTest`, `Exception`, `TestException` protokolliert.
Aussage: Das System soll Lieferantendokumente in konfigurierbaren Intervallen automatisch abrufen, formatabhängig einlesen, den zugehörigen Bestellungen zuordnen und jeden Verarbeitungsvorgang mit seinem Ergebnis protokollieren.
Ergebnis: Erfolgreich verarbeitete Dateien werden entfernt und protokolliert; fehlerhafte Dateien bleiben mit Fehlerprotokoll erhalten.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37 – Begründung: Startverzögerung und Intervall.
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs sowie die Partial-Dateien je Format – Begründung: Implementierte Verteilung und Formatverarbeitung.
- [KONTEXT] docs/reference/edi/edi-architecture.md:91-107, 237-266 – Begründung: Beschreibt Dispatch-Methode, Protokollzustände und Fehlerstrategien.
- [KONTEXT] docs/reference/edi/edi-import-rules.md – Begründung: Ergänzende Importregeln.
Prüfidee: Fehlerhafte EDI-Datei bereitstellen; nach dem nächsten Lauf muss ein Logeintrag mit `DownloadError` existieren und die Datei erhalten bleiben.
Tracelinks: StRS-014, StRS-006, SwRS-046
Konsolidierung: nein
Status: belegt
```
---
## 5. Betrieb, Wartung und Qualitätsanforderungen
```
ID: SyRS-025
Titel: Definierte Ausführungsintervalle der Hintergrunddienste
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz, Zuverlässigkeit)
Akteur: Hintergrunddienst
Vorbedingung: Der Web-Service läuft.
Fakt: Jeder Dienst deklariert `GetExecutionInterval()`. Gemessene Werte: `CallTrackingService` und `CacheUpdateService` 2 s; `ReminderService` 1 s; `SendMyDayNotificationsService` 20 s; `ObjectFulltextIndexUpdateService`, `DocumentFulltextIndexUpdateService`, `CampaignPhaseService`, `ConnectionTicketService`, `TelemetryFlushService` 1 min; `MassUpdateService`, `GfkExportService` 5 min; `CTimeConnectorService`, `EscalationsService`, `FlushAnalyticEventsService`, `TelemetryUploadService` 15 min; `ArticleImportService`, `EdiDownloadService`, `RecurringScriptService`, `SendEmailForUnreadMessagesService`, `AutoMapperMissingMappingsService` 30 min; `AutomaticPriceUpdateService`, `DataQualityService`, `RefreshIntakeService`, `PlmImportService`, `UpdateArticleAndMaterialGroupTaxRatesService`, `UpdateExpiredProvisionSchemasService`, `ValidateHelpdeskFingerprintService` 1 h; `TodoService` 6 h; `ContractCloseService`, `ContractEndeService` 1 Tag; `UpdateSpecialArticleToContractService` 30 Tage. `ObjectFulltextIndexUpdateService` und `TaskManagmentService` begrenzen ihre Laufzeit zusätzlich über `CancelAfter(15 min)` bzw. `CancelAfter(10 min)`.
Aussage: Das System soll jede Hintergrundaufgabe in einem ihrer fachlichen Dringlichkeit entsprechenden Intervall zwischen 1 Sekunde und 30 Tagen ausführen und für langlaufende Aufgaben eine harte Laufzeitgrenze setzen.
Ergebnis: Die Wiederholrate jedes Dienstes ist nachweisbar; kein Einzellauf blockiert den Dienst dauerhaft.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (33 Klassen, jeweils `GetExecutionInterval()`) – Begründung: Vollständige, im Code verankerte Intervalltabelle.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ObjectFulltextIndexUpdateService.cs:72 und TaskManagmentService.cs:78 (`CancelAfter`) – Begründung: Belegt die Laufzeitbegrenzung.
Prüfidee: Log über eine Stunde auswerten; `DataQualityService` darf genau einen und `EdiDownloadService` genau zwei Läufe aufweisen.
Tracelinks: StRS-018, SwRS-034
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-026
Titel: Zentrale Steuerung und Fehlerresilienz der Hintergrunddienste
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Zuverlässigkeit, Wartbarkeit)
Akteur: Administrator, Hintergrunddienst
Vorbedingung: Der Dienst ist gestartet.
Fakt: `ManagedBackgroundService` wartet nach dem Start zunächst 1 Minute, persistiert die Startzeit (`UpdateStartTime`) und prüft anschließend vor jedem Lauf über `BackgroundServiceBL.IsServiceEnabled(serviceName)`, ob der Dienst aktiv ist; das Ergebnis wird 60 Sekunden zwischengespeichert. Bei Ausnahmen wird `_consecutiveFailures` erhöht, `DAOFactory.Instance.TryRecoverConnectionPool(exception)` aufgerufen und die nächste Wartezeit exponentiell verlängert (`base * 2^failures`), gedeckelt auf 5 Minuten. Kann der Aktivierungszustand nicht gelesen werden, gilt der letzte bekannte Wert, ersatzweise „deaktiviert", um keine weiteren Datenbankverbindungen zu verbrauchen.
Aussage: Das System soll jeden Hintergrunddienst zentral über die Datenbank aktivierbar halten, seine Start- und letzte Laufzeit persistieren und bei wiederholten Fehlern die Ausführungsfrequenz exponentiell bis auf maximal fünf Minuten reduzieren.
Ergebnis: Ein dauerhaft fehlschlagender Dienst belastet das System nicht durch enge Wiederholungen; der Betriebszustand ist aus der Datenbank ablesbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-157 – Begründung: Enthält Aktivierungsprüfung, Cache, Backoff und Verbindungspool-Wiederherstellung vollständig.
- [KONTEXT] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:96-100, 133 (Kommentare zur Verbindungspool-Erschöpfung) – Begründung: Belegt, dass die Resilienzlogik als Reaktion auf einen realen Betriebsfehler eingeführt wurde.
Prüfidee: Datenbank während des Betriebs abschalten; die Logabstände eines Minutendienstes müssen sich schrittweise bis auf maximal fünf Minuten verlängern.
Tracelinks: StRS-018, SwRS-034
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-027
Titel: Automatische Datenbankschema-Migration beim Start
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Wartbarkeit, Übertragbarkeit)
Akteur: Administrator, System
Vorbedingung: Der Web-Service startet und besitzt eine gültige Lizenz für `ApplicationKind.Centron`.
Fakt: `ScriptEngineBL.ExecuteScripts` ermittelt alle registrierten Skriptmethoden, vergleicht sie mit den bereits ausgeführten Einträgen der Tabelle `DBUpdate` (`ScriptNumber`) und führt die fehlenden in der Reihenfolge `MethodKind`, `ApplicationVersion`, `ScriptNumber` aus, sofern `currentVersion >= method.ApplicationVersion`. Es existieren 764 Skriptklassen unter `ScriptMethods/Scripts`. Fehlgeschlagene Skripte brechen den Vorgang ab, sofern ihre Nummer nicht in `_scriptIgnoreIfErrorList` steht. `LicenseManager.LoadLicenses` prüft die Lizenz **vor** der Schemaaktualisierung mit dem ausdrücklichen Kommentar, dass eine Aktualisierung ohne Lizenz den Kunden von älteren Clients aussperren würde.
Aussage: Das System soll das Datenbankschema beim Start des Anwendungsservers automatisch auf den Stand der laufenden Programmversion bringen, jedes Skript genau einmal ausführen und die Aktualisierung ohne gültige Produktlizenz verweigern.
Ergebnis: Nach dem Start entspricht das Schema der Programmversion; `DBUpdate` enthält je ausgeführtem Skript genau einen Eintrag.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177 – Begründung: Vollständiger Migrationsalgorithmus inkl. Idempotenz über `DBUpdate` und Fehlerbehandlung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:219-236 (`LoadLicenses`) – Begründung: Durchgesetzte Lizenzvorbedingung vor der Schemaänderung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/ (764 Dateien, z. B. ScriptMethod11803.cs) – Begründung: Belegt Umfang und Form der Migrationsschritte (idempotente DDL über `ScriptHelpers.AddColumnIfNotExists` plus vollständige `ALTER VIEW`-Anweisungen).
- [KONTEXT] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:226-233 (Kommentarblock) – Begründung: Begründet die Reihenfolge Lizenzprüfung vor Migration fachlich.
- [KONTEXT] docs/guides/database/create-scripts.md – Begründung: Beschreibt den organisatorischen Prozess der Skriptnummernreservierung.
Prüfidee: Datenbank mit einem `DBUpdate`-Eintrag für Skript 11803 versehen und den Dienst starten; das Skript darf nicht erneut ausgeführt werden.
Tracelinks: StRS-004, StRS-024, SwRS-036, SwRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-028
Titel: Zweisprachige Benutzeroberfläche mit deutscher Basissprache
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Gebrauchstauglichkeit, Übertragbarkeit)
Akteur: Interner Benutzer
Vorbedingung: keine
Fakt: Lokalisierte Texte liegen als .NET-Ressourcen vor: `LocalizedStrings.resx` (deutsche Basisdatei) und `LocalizedStrings.en.resx` (englische Übersetzung). Insgesamt wurden 14 `.resx`-Dateien im Repository gefunden. Ein Teil der Meldungen ist jedoch als deutsches Stringliteral direkt im Quelltext hinterlegt (siehe StRS-019).
Aussage: Das System soll benutzersichtbare Texte über ein Ressourcensystem mit deutscher Basissprache und englischer Übersetzung bereitstellen.
Ergebnis: Bei englischer Spracheinstellung erscheinen übersetzte Texte; nicht übersetzte Schlüssel fallen auf Deutsch zurück.
Belege:
- [PRIMÄR] Verwendung von `Centron.BusinessLogic.Resources.LocalizedStrings` in AuthenticatorFactory.cs:74, BasicAuthenticator.cs:40, Authenticator.cs:74 – Begründung: Belegt die produktive Nutzung des Ressourcensystems im Anmeldepfad.
- [SEKUNDÄR] ResXManager.config.xml (Repositorywurzel) – Begründung: Werkzeugkonfiguration für die Ressourcenpflege belegt einen etablierten Übersetzungsprozess.
- [KONTEXT] docs/guides/ui/localization.md, docs/getting-started/general-structure.md:126-133 – Begründung: Beschreibt Basisdatei- und Übersetzungskonvention.
Prüfidee: Neuen Schlüssel nur in der deutschen Basisdatei anlegen und die Oberfläche auf Englisch stellen; der deutsche Text muss ohne Fehler erscheinen.
Tracelinks: StRS-019, SwRS-051
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-029
Titel: Protokollierung sicherheitsrelevanter Ereignisse
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Wartbarkeit)
Akteur: Administrator
Vorbedingung: Der Web-Service ist konfiguriert und NLog aktiv.
Fakt: Anmeldeversuche werden mit `Logger.Info("Basic authentication attempt ({RequestId}) received for user: {UserName}.")` bzw. `Logger.Warn("Basic authentication failed for user: {UserName}. Context: {AuthObject}")` protokolliert. `AuthObject.ToString()` liefert Request-ID, Anwendungsversion, Anwendungsname, Maschinenname und IP-Adresse; das Kennwort ist nicht Teil der Ausgabe. Zugriffe über Access Tokens werden über `AccessTokenLogBL` mit IP-Adresse und aufgerufener API-Methode protokolliert. Die IP-Ermittlung berücksichtigt `X-Forwarded-For` und `X-Real-IP` vor der Verbindungsadresse.
Aussage: Das System soll erfolgreiche und fehlgeschlagene Anmeldeversuche sowie Access-Token-Verwendungen mit Zeitpunkt, Benutzer, Anwendung, Gerät und Quell-IP protokollieren, ohne Geheimnisse in das Protokoll zu schreiben.
Ergebnis: Ein fehlgeschlagener Anmeldeversuch ist im Serverprotokoll mit Kontext nachvollziehbar; das Kennwort erscheint nicht.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:45,55,58,67 – Begründung: Belegt Protokollierung an allen Verzweigungen des Anmeldepfads.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:22-42 (`AuthObject.ToString`, `RemoteAddress`) – Begründung: Definiert den protokollierten Kontextumfang und schließt das Kennwort aus.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:147-172 – Begründung: Proxy-taugliche IP- und Methodenermittlung für das Zugriffsprotokoll.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:2-23 (NLog-Ziele Konsole und CSV-Datei, Regel `minLevel: Warn`) – Begründung: Belegt die konfigurierbare Protokollablage und -schwelle.
Prüfidee: Anmeldung mit falschem Kennwort durchführen; das Protokoll muss einen `Warn`-Eintrag mit Benutzername, Anwendung und IP, aber ohne Kennwort enthalten.
Tracelinks: StRS-017, SyRS-004, SyRS-009
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-030
Titel: Revisionsprotokoll für Änderungen an Rechten und Gruppen
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator
Vorbedingung: Ein Administrator ändert Rechtegruppen oder -zuordnungen.
Fakt: `AppRightsBL` schreibt für sechs Ereignisarten (`AddRightToGroup`, `RemoveRightFromGroup`, `CreateGroup`, `DeleteGroup`, `AddUserToGroup`, `RemoveUserFromGroup`, `CopyGroup`) einen `AppRightLog`-Eintrag mit `CreatedByI3D` (Mitarbeiter), `CreatedDate`, `CreatedVersion` (Assembly-Version), `Kind`, `Object` und einer deutschen Beschreibung, z. B. `Recht "{X}" an die Gruppe "{Y}" vergeben`. Die Administratorengruppe (`I3D == 6` bzw. Name „Administratoren") kann nicht gelöscht werden; für sie sind nur 34 explizit gelistete Rechte zuweisbar bzw. entziehbar.
Aussage: Das System soll jede Änderung an Rechtegruppen, Rechtezuordnungen und Gruppenmitgliedschaften revisionssicher mit Urheber, Zeitpunkt und Programmversion protokollieren und die Administratorengruppe gegen Löschung und gegen Entzug ihrer Kernrechte schützen.
Ergebnis: Rechteänderungen sind lückenlos nachvollziehbar; die Administratorengruppe bleibt handlungsfähig.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-857 (`WriteBaseLog` und sechs Spezialisierungen) – Begründung: Durchgesetzte Protokollierung für alle Änderungsarten.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:359-360 – Begründung: Löschschutz der Administratorengruppe.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:714-759 (`GetAssignableAdminRightI3Ds`) – Begründung: Abschließende Liste der bei Administratoren änderbaren Rechte.
Prüfidee: Recht einer Gruppe zuweisen; in `AppRightLog` muss ein Eintrag mit Kind `AddRightToGroup` und dem ausführenden Mitarbeiter entstehen.
Tracelinks: StRS-002, StRS-015, SwRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-031
Titel: Feldgenaue Protokollierung fachlicher Belegänderungen
Ebene: SyRS
Typ: funktional / Compliance
Akteur: Interner Benutzer, Wirtschaftsprüfer
Vorbedingung: Ein bestehender Beleg wird geändert.
Fakt: `ReceiptBL.WriteReceiptLogs` vergleicht bei Belegen mit Kontingent 16 Einzelfelder (u. a. `ContingentKind`, `ContingentValue`, `ContingentMinimalOrderAmount`, `ContingentBalanceArticleI3D`, `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentLimitValue`) zwischen alter und neuer Version und erzeugt je Abweichung über `ReceiptLogBL` einen eigenen Logeintrag mit Alt- und Neuwert, Zeitpunkt und Benutzer. Weitere Einträge entstehen für Zahlungsstatus (`CreateSetAsPaidEntry`) und Zahlbetrag (`CreatePaidFCChangedEntry`).
Aussage: Das System soll Änderungen an abrechnungsrelevanten Belegfeldern einzeln mit Alt- und Neuwert protokollieren.
Ergebnis: Zu jeder Feldänderung existiert ein eigener, auswertbarer Protokolleintrag.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369 – Begründung: Zeigt den feldweisen Vergleich und die je Feld eigene Logmethode.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4949, 4957 (`CreateSetAsPaidEntry`, `CreatePaidFCChangedEntry`) – Begründung: Protokollierung im Zahlungspfad.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:123-143 (`AnlageLog` mit `AnlageI3D` + `AnlageArt`) – Begründung: Beschreibt die gemeinsame Logtabelle über alle Belegarten.
Prüfidee: Kontingentwert eines Vertrags ändern und speichern; im Belegprotokoll muss genau ein Eintrag mit altem und neuem Wert entstehen.
Tracelinks: StRS-015, SyRS-016
Konsolidierung: Kandidat: `ReceiptLogBL` (74 KB) enthält eine eigene Methode je Feld; im Zielsystem durch ein generisches, metadatengetriebenes Änderungsprotokoll ersetzbar.
Status: belegt
```
```
ID: SyRS-032
Titel: Verschlüsselte Ablage von Verbindungsgeheimnissen
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator
Vorbedingung: Der Web-Service besitzt eine `WebServiceConfig.xml`.
Fakt: `WebServiceConfigSerializer` liest `DatabaseConnectionString`, `ProxyPassword`, `RadiusServerSecret` und `AdditionalService.SqlPassword` über `new AESCryptoLogic().DecryptText(...)` und schreibt sie beim Speichern über `EncryptText(...)`. Ist `DatabaseConnectionString` leer, wird ersatzweise das **unverschlüsselte** Feld `DatabaseConnectionStringPlain` verwendet. Die mitgelieferte Container-Konfiguration nutzt genau diesen Klartextpfad (`Server=db; Database=Centron; User Id=SA; Password=SA!password`) und enthält zudem einen fest eingetragenen `SecretKey`, der identisch in `appsettings.Production.json` des Nexus wiederkehrt.
Aussage: Das System soll Verbindungsgeheimnisse in der Konfigurationsdatei verschlüsselt ablegen; der weiterhin unterstützte Klartextpfad ist ausschließlich für Entwicklungs- und Containerumgebungen vorgesehen und darf im Produktivbetrieb nicht verwendet werden.
Ergebnis: Produktivkonfigurationen enthalten keine Klartextgeheimnisse.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:30, 41, 56, 76, 88, 163 – Begründung: Zeigt Ver- und Entschlüsselung der vier Geheimnisfelder.
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:42-45 – Begründung: Belegt den Klartext-Fallback als bewusst implementierten Pfad.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:11-15, 33 – Begründung: Auslieferungsbeispiel nutzt Klartext-Verbindungszeichenfolge und einen mitgelieferten `SecretKey`.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:39-41 – Begründung: Derselbe `SecretKey` ist auch in der Nexus-Beispielkonfiguration hinterlegt.
Prüfidee: Produktivkonfiguration prüfen: `DatabaseConnectionStringPlain` muss leer sein und `DatabaseConnectionString` einen Chiffretext enthalten; der `SecretKey` darf nicht dem Auslieferungsbeispiel entsprechen.
Tracelinks: StRS-024, SwRS-039
Konsolidierung: nein
Status: belegt; Workaround – der Klartextpfad `DatabaseConnectionStringPlain` und die mitgelieferten Beispielgeheimnisse sind ein bekanntes Betriebsrisiko und in der Migration zu entfernen
```
```
ID: SyRS-033
Titel: Transportverschlüsselung und Zertifikatskonfiguration
Ebene: SyRS
Typ: Sicherheit / nicht-funktional (ISO 25010: Sicherheit)
Akteur: Administrator
Vorbedingung: Der Web-Service bzw. der Nexus-Host wird betrieben.
Fakt: `WebServiceConfig` enthält `WebServiceCertificateFilePath` und `WebServiceCertificatePassword`; die Nexus-Konfiguration enthält `Host.LinuxCertificatePath` und `Host.LinuxCertificatePassword`. Die mitgelieferten Beispielkonfigurationen verwenden jedoch durchgängig `http://` (`http://localhost:1234/CentronService`, `http://localhost:8050`, `http://webservice:1234/CentronService`) und leere Zertifikatsfelder.
Aussage: Das System soll die Kommunikation zwischen Clients, Web-Service und Webanwendung über TLS absichern können; die Aktivierung erfolgt durch Hinterlegen eines Serverzertifikats in der Betriebskonfiguration.
Ergebnis: Bei hinterlegtem Zertifikat werden Endpunkte über HTTPS bereitgestellt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfigSerializer.cs:35-36 – Begründung: Zertifikatsfelder sind Teil der Serverkonfiguration.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:24-28 (`LinuxCertificatePath`, `LinuxCertificatePassword`) – Begründung: Analoge Konfiguration für die Webanwendung.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml:3-6 und docker/compose/appsettings.Production.json:25,31 – Begründung: Belegt, dass die Auslieferungsbeispiele unverschlüsselt (`http://`) konfiguriert sind.
Prüfidee: Zertifikat hinterlegen und den Dienst neu starten; der Endpunkt muss über `https://` erreichbar sein und `http://` abgewiesen bzw. umgeleitet werden.
Tracelinks: StRS-024, SyRS-032
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – dass bei hinterlegtem Zertifikat unverschlüsselte Aufrufe abgewiesen oder umgeleitet werden, ist nicht belegt; siehe HYP-002
```
```
ID: SyRS-034
Titel: Portbasierte Trennung von Mitarbeiter- und Kundenportal
Ebene: SyRS
Typ: Sicherheit
Akteur: Administrator, Interner Benutzer, Web-Account
Vorbedingung: Die Webanwendung Nexus ist konfiguriert.
Fakt: `PortAuthorization` registriert die Richtlinien `CentronAuthorization.HostPort` (Standardport 8050) und `CentronAuthorization.CustomerPortalPort`. Ist `CustomerPortalConfig.Port` nicht gesetzt, gilt die Anforderung als erfüllt und der Kundenportalport wird auf den Hostport gesetzt. Andernfalls wird `HttpContext.Connection.LocalPort` gegen den erlaubten Port geprüft und bei Abweichung eine Warnung protokolliert. Ergänzend existieren die Autorisierungsattribute `AuthorizeHostPortAttribute` und `AuthorizeCustomerPortalPortAttribute`.
Aussage: Das System soll das interne Mitarbeiterportal und das externe Kundenportal auf getrennten Netzwerkports bereitstellen können, sodass Seiten des jeweils anderen Portals über den falschen Port nicht erreichbar sind.
Ergebnis: Bei konfiguriertem Kundenportalport sind mit `AuthorizeHostPort` markierte Seiten über den Kundenportalport nicht zugänglich.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/PortAuthorization.cs:17-71 – Begründung: Vollständige, durchgesetzte Portprüfung inkl. Standardwerten.
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/Attributes/AuthorizeHostPortAttribute.cs, AuthorizeCustomerPortalPortAttribute.cs – Begründung: Anwendbare Markierung je Seite.
- [SEKUNDÄR] docker/compose/appsettings.Production.json:33-35 (`CustomerPortal.Port: null`) – Begründung: Belegt, dass die Trennung im Auslieferungsbeispiel deaktiviert ist.
Prüfidee: `CustomerPortal.Port` auf 8060 setzen; ein Aufruf einer `AuthorizeHostPort`-Seite über Port 8060 muss abgewiesen und im Protokoll als „Port 8060 is not allowed" vermerkt werden.
Tracelinks: StRS-003, StRS-024, SwRS-041
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-035
Titel: Rechteprüfung beim Speichern eines Tickets
Ebene: SyRS
Typ: Sicherheit
Akteur: Interner Benutzer, Web-Account
Vorbedingung: Ein Ticket wird angelegt oder geändert.
Fakt: `HelpdeskBL.DoBeforeSave` ruft `CheckRights`, das nach Anmeldeart verzweigt. Für interne Benutzer gilt: Neuanlage erfordert `ADD_NEW_HELPDESK`; Änderung erfordert `EDIT_HELPDESK`; das Setzen des als „geschlossen" konfigurierten Status erfordert zusätzlich `CLOSE_REQUEST`; ohne `MATURITY_CHANGE` darf das Fälligkeitsdatum nicht verändert werden (geprüft über `HelpdeskRepositoryDAO.IsDueDateChanged`); mit `ASSIGN_HELPDESK_ONLY_TO_OWN_DEPARTMENTS` muss die geänderte verantwortliche Person einer eigenen Abteilung angehören. Wird ein anderer als der Abschlussstatus gesetzt, wird `ClosedAt` zurückgesetzt.
Aussage: Das System soll beim Speichern eines Tickets alle betroffenen Einzelrechte prüfen und dabei zwischen Anlegen, Ändern, Abschließen, Fälligkeitsänderung und Zuweisung unterscheiden; der Abschlusszeitpunkt soll automatisch zurückgesetzt werden, sobald das Ticket wieder geöffnet wird.
Ergebnis: Unzulässige Änderungen werden mit einer spezifischen deutschen Meldung und `RightCheckFailed` abgewiesen; `ClosedAt` ist genau dann gesetzt, wenn das Ticket im Abschlussstatus ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:310-326, 410-466 – Begründung: Vollständige, durchgesetzte Prüfkette im Speicherpfad.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:440-443 (`entity.ClosedAt = null`) – Begründung: Automatische Rücksetzung des Abschlusszeitpunkts.
- [KONTEXT] CentronRights.md:19-48 – Begründung: Beschreibt die beabsichtigte Wirkung der einzelnen Ticketrechte.
Prüfidee: Ticket ohne `MATURITY_CHANGE` mit geändertem Fälligkeitsdatum speichern; der Vorgang muss mit „Kein Recht für Fälligkeitsdatum ändern vorhanden." scheitern.
Tracelinks: StRS-008, SyRS-013, SwRS-043
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-036
Titel: Konfigurierbares Ticket-Statusmodell
Ebene: SyRS
Typ: Daten / funktional
Akteur: Administrator
Vorbedingung: keine
Fakt: Der Ticketstatus ist keine feste Aufzählung, sondern eine Stammdatenreferenz (`HelpdeskCompact.HelpdeskStateI3D` mit Anzeigetext `HelpdeskStateCaption`). Der fachlich besondere Zustand „geschlossen" wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfiguriert. Analog sind Priorität (`HelpdeskPriorityI3D`), Typ (`HelpdeskTypeI3D`) sowie Haupt- und zwei Unterkategorien als Stammdaten modelliert; im WPF-Client existieren dafür die Einstellungsmodule `Helpdesk.Settings.Status`, `.Priorities`, `.Types`, `.Categories`.
Aussage: Das System soll Ticketstatus, -prioritäten, -typen und -kategorien als vom Betreiber pflegbare Stammdaten führen und den abschließenden Status als konfigurierbare Auszeichnung eines dieser Statuswerte behandeln.
Ergebnis: Betreiber können eigene Statuswerte anlegen; die Abschlusslogik bleibt an den als „geschlossen" markierten Wert gebunden.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:17-22, 57-62 – Begründung: Status, Priorität, Typ und Kategorien sind Fremdschlüssel, keine Enumerationen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`GetClosedHelpdeskState()`) – Begründung: Der Abschlussstatus wird zur Laufzeit aus den Einstellungen gelesen.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:105,110,112,114 – Begründung: Eigene Pflegemodule für Kategorien, Prioritäten, Status und Typen.
Prüfidee: Zusätzlichen Ticketstatus anlegen und einem Ticket zuweisen; das Ticket darf dabei nicht als abgeschlossen gelten und `ClosedAt` muss leer bleiben.
Tracelinks: StRS-008, SyRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-037
Titel: Vierstufiges Mahnwesen mit Mahnstopp
Ebene: SyRS
Typ: funktional
Akteur: Interner Benutzer (Debitorenbuchhaltung)
Vorbedingung: Es existieren offene Rechnungen mit überschrittenem Zahlungsziel.
Fakt: `DunningBL` kennt die Stufen `DunningLevel.None`, `Level1`, `Level2`, `Level3` und ermittelt je Stufe Anzahl und Summe des offenen Bruttobetrags als `GrossPriceComplete - PayedGrossAmount - CreditVoucherGrossAmount`. Gutschriften werden über `CreditVoucherDunning` in denselben Mahnkreis einbezogen (`customers.Union(creditVouchers)`). `UpdateDunningStopAndInfo(objectI3D, objectKind, dunningStop, dunningInfo, dunningStopBegin, dunningStopEnd, loggedInUser)` setzt einen Mahnstopp wahlweise auf Kunden- oder Rechnungsebene; Beginn wird auf Tagesanfang, Ende auf Tagesende normalisiert.
Aussage: Das System soll offene Forderungen in vier Mahnstufen führen, Gutschriften saldierend berücksichtigen und einen tagesgenau befristeten Mahnstopp je Kunde oder je Beleg zulassen.
Ergebnis: Der ausgewiesene offene Betrag ist um Zahlungen und Gutschriften bereinigt; Belege mit aktivem Mahnstopp bleiben unberücksichtigt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231 – Begründung: Vier Stufen und Berechnungsformel des offenen Betrags.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:392-431 – Begründung: Mahnstopp auf zwei Objektebenen mit Zeitraumnormalisierung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs:117,139 (`customers.Union(creditVouchers)`) – Begründung: Belegt die gemeinsame Betrachtung von Rechnungen und Gutschriften.
Prüfidee: Rechnung über 100 € mit Gutschrift über 40 € und Zahlung über 20 €; der ausgewiesene offene Betrag muss 40 € betragen.
Tracelinks: StRS-013, SwRS-033
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-038
Titel: DSGVO-konforme Anonymisierung von Kontaktdaten
Ebene: SyRS
Typ: Sicherheit / Compliance
Akteur: Administrator (Datenschutzbeauftragter)
Vorbedingung: Der Benutzer besitzt das Recht `DsgvoModule.DSGVO_DELETE_CONTACT`.
Fakt: `DataSecurityBL.DsgvoDeleteRightDeleteContacts` verarbeitet ausschließlich die Kontakttypen Ansprechpartner (Kunde und Lieferant), Kontaktmanagement-Ansprechpartner und Account-Adresskontakt über `DoDeleteContactPerson`, `DoDeleteContactManagementContactPerson`, `DoDeleteAccountAddressContact`. Die Pfade für Kunde, Lieferant, Kontaktmanagement-Kontakt und Account sind auskommentiert bzw. werfen `NotImplementedException`. Über alle Vorgänge wird ein Löschprotokoll (`deleteProtocol`) geführt und als Text zurückgegeben.
Aussage: Das System soll das Löschbegehren betroffener Personen für Ansprechpartner durch Anonymisierung und Deaktivierung erfüllen und den Vorgang protokollieren; für Kunden-, Lieferanten- und Account-Stammsätze ist diese Funktion derzeit nicht verfügbar.
Ergebnis: Anonymisierte Ansprechpartner tragen den Text „DSGVO: Auf Anfrage gelöscht. (Durchgeführt von … am … um … Uhr)"; ein Protokoll dokumentiert den Vorgang.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:787-855 – Begründung: Zeigt die tatsächlich implementierten und die auskommentierten Löschpfade.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:856-1030 (`NotImplementedException` und auskommentierte SQL-Anweisungen) – Begründung: Belegt den unfertigen Zustand für Stammsätze.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 – Begründung: Definiert den Anonymisierungstext inklusive Nachweis des Ausführenden.
Prüfidee: DSGVO-Löschung für einen Ansprechpartner ausführen und das zurückgegebene Protokoll prüfen; es muss den anonymisierten Datensatz benennen.
Tracelinks: StRS-016, SwRS-047
Konsolidierung: nein
Status: belegt; Workaround – unvollständige Implementierung, in der Validierung mit hoher Priorität zu klären
```
```
ID: SyRS-039
Titel: Vermeidung redundanter Belegdokumente
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz)
Akteur: System
Vorbedingung: Ein Belegreport wird als PDF erzeugt und abgelegt.
Fakt: `ReceiptBL.AddReportPdf` ruft vor der Ablage `DocumentsBL.GetIdenticalDocumentInDirectory(directoryI3D, name, reportPdf, receipt.Version)` und gibt bei Treffer die bestehende Dokument-I3D zurück, ohne ein neues Dokument anzulegen. Der Kommentar verweist auf Ticket 160276 und begründet dies damit, dass ein erneuter Export derselben Belegversion ein bytegleiches PDF erzeugt.
Aussage: Das System soll bei wiederholtem Export derselben Belegversion mit demselben Report kein zusätzliches Dokument speichern, sondern das bestehende referenzieren.
Ergebnis: Der Dokumentenspeicher wächst nicht durch wiederholte Exporte derselben Belegversion.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3483 – Begründung: Durchgesetzte Dublettenprüfung vor der Ablage.
- [KONTEXT] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3476 (Ticketreferenz 160276) – Begründung: Weist die Regel als nachträgliche Korrektur eines Betriebsproblems aus.
Prüfidee: Denselben Beleg fünfmal exportieren; im Belegordner darf nur ein Dokument entstehen.
Tracelinks: StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-040
Titel: Verteilte Betriebstopologie
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit, Wartbarkeit)
Akteur: Administrator
Vorbedingung: keine
Fakt: Die `compose.yaml` definiert vier Dienste: `db` (MSSQL-Image), `webservice` (Start über `/app/Centron.Host.Console`, Containerport 1234, veröffentlicht als 4321, Konfiguration über eingebundene `WebServiceConfig.xml`, `restart: on-failure`, Umgebungsvariable `HARDWARE_ID`), `smtp` (Mailcatcher, Ports 1025/1080) und `nexus` (Start über `/app/CentronNexus.Host`, Port 8050, Konfiguration über `appsettings.Production.json`, abhängig vom Web-Service). Nexus erreicht den Web-Service über `http://webservice:1234/CentronService`. Zusätzlich existieren Windows-Installationspakete (WiX) für Client und Web-Service.
Aussage: Das System soll aus einer Datenbank, einem Anwendungsserver, einer Webanwendung und optionalen Zusatzdiensten bestehen, die netzwerkseitig getrennt betrieben und über konfigurierbare Endpunkte verbunden werden.
Ergebnis: Die Komponenten sind unabhängig deploybar; die Webanwendung greift ausschließlich über den Anwendungsserver auf die Datenbank zu.
Belege:
- [PRIMÄR] docker/compose/compose.yaml:1-54 – Begründung: Vollständige Topologiedefinition mit Abhängigkeiten und Ports.
- [PRIMÄR] docker/compose/appsettings.Production.json:30-32 (`CentronWebService.Url`) – Begründung: Belegt, dass Nexus den Web-Service als einzige Datenquelle adressiert.
- [PRIMÄR] deployment/centron/CentronSetupProject/Product.wxs, deployment/centron/WebServiceSetupProject/Product.wxs – Begründung: Getrennte Installationspakete für Client und Server.
- [SEKUNDÄR] docker/c-entron-webservice/Dockerfile, docker/c-entron-api/Dockerfile – Begründung: Containerisierung der Serverkomponenten.
Prüfidee: Web-Service-Container stoppen; Nexus muss weiterlaufen, aber jede fachliche Aktion mit einem Verbindungsfehler quittieren.
Tracelinks: StRS-024, SwRS-048
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-041
Titel: Umschaltbare Datenzugriffsart des Fachclients
Ebene: SyRS
Typ: Schnittstelle / nicht-funktional (ISO 25010: Übertragbarkeit)
Akteur: Administrator, Interner Benutzer
Vorbedingung: Der Client ist mit einer Verbindung vom Typ `SqlServer` oder `CentronWebServices` konfiguriert.
Fakt: Jedes Clientmodul deklariert in seinem `AppModuleController` über `SupportsConnectionTypes` die unterstützten Verbindungsarten (`CentronConnectionType.CentronWebServices`, `CentronConnectionType.SqlServer`). Der `ClassContainer` löst zur Laufzeit die Schnittstelle `I{Modul}Logic` gegen `BL{Modul}Logic` (direkter Datenbankzugriff) oder `WS{Modul}Logic` (Web-Service-Aufruf) auf. Beide Implementierungen liefern `Task<Result<T>>`.
Aussage: Das System soll denselben Fachclient wahlweise mit direktem Datenbankzugriff oder über den Anwendungsserver betreiben können, wobei jedes Modul angibt, welche Betriebsarten es unterstützt.
Ergebnis: Ein Modul, das eine Verbindungsart nicht unterstützt, wird in dieser Betriebsart nicht angeboten.
Belege:
- [KONTEXT] docs/getting-started/general-structure.md:15-113 – Begründung: Beschreibt Muster, Namenskonvention und die Pflicht zur Doppelimplementierung ausführlich; die Codebeispiele stammen aus `IAccountContractsLogic`.
- [PRIMÄR] src/centron/Centron.WPF.UI/Services/ (688 Dateien mit `BL*Logic`/`WS*Logic`-Paaren) – Begründung: Die Doppelimplementierung ist in der Codebasis breit umgesetzt.
- [PRIMÄR] src/webservice/c-entron.misc.ConnectionManager/ – Begründung: Eigene Komponente zur Verbindungsverwaltung.
Prüfidee: Client mit Verbindungsart `CentronWebServices` starten; ein Modul, das nur `SqlServer` deklariert, darf nicht im Menü erscheinen.
Tracelinks: StRS-024, SwRS-001, SwRS-002
Konsolidierung: Kandidat: SwRS-002 – jede Fachfunktion existiert doppelt (BL- und WS-Variante); im Zielsystem als reine Web-/SaaS-Architektur auf einen Pfad zu reduzieren.
Status: belegt; Teilaussage [HYPOTHESE] – die Vollständigkeit der Doppelimplementierung über alle Module ist nicht verifiziert; siehe HYP-006
```
```
ID: SyRS-042
Titel: Stapelverarbeitung großer Datenmengen
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Performanz-Effizienz)
Akteur: System
Vorbedingung: Eine Operation betrifft eine große Menge von Datensätzen.
Fakt: Massenoperationen zerlegen Schlüssellisten vor der Datenbankabfrage in Blöcke zu 2 000 Elementen: `TaxBL.UpdateArticleVATs` verarbeitet `articleI3DsWithOldTaxRate.Batch(2000)`; `AutomaticFacturaBL.SearchBillingContracts` verwendet an fünf Stellen `.Batch(2000)` vor benannten Abfragen. Ergänzend existieren Cache-Mechanismen (`Session.Advanced.Cache.GetOrAdd`) und ein `CacheUpdateService` mit 2-Sekunden-Takt und 1-Minuten-Optimierungsintervall.
Aussage: Das System soll Datenbankabfragen mit Listenparametern in Blöcken von höchstens 2 000 Schlüsseln ausführen, um Grenzen des Datenbanksystems einzuhalten und die Antwortzeit zu begrenzen.
Ergebnis: Auch Operationen über zehntausende Datensätze werden ohne Abfragefehler ausgeführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/TaxBL.cs:117 (`Batch(2000)`) – Begründung: Konkrete, durchgesetzte Blockgröße.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:861, 890, 898, 910, 924 – Begründung: Dieselbe Blockgröße an fünf weiteren Stellen belegt die Konvention.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/CacheUpdateService.cs:30,46 – Begründung: Ergänzende Cache-Strategie zur Lastreduktion.
Prüfidee: Steuersatzumstellung für 5 000 Artikel auslösen; die Operation muss ohne Parameterlimit-Fehler durchlaufen und in drei Blöcken erfolgen.
Tracelinks: StRS-007, SwRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: SyRS-043
Titel: Erhebung und Übermittlung von Betriebstelemetrie
Ebene: SyRS
Typ: nicht-funktional (ISO 25010: Wartbarkeit) / Datenschutz
Akteur: Lizenzgeber (NEXOWARE), Administrator
Vorbedingung: Die Telemetriedienste sind aktiviert.
Fakt: Der Web-Service enthält eine Telemetriekomponente mit `TelemetryAggregator`, `HttpTelemetryUploadClient`, `DatabaseGuidProvider` und `HardwareIdProvider`. `TelemetryFlushService` schreibt im Minutentakt, `TelemetryUploadService` überträgt alle 15 Minuten. Der `ApiCallTelemetryInterceptor` und der `McpToolUsageTelemetryInterceptor` erfassen API-Aufrufe. `CentronAnalytics` und `FlushAnalyticEventsService` (15 min) erfassen Nutzungsereignisse.
Aussage: Das System soll Nutzungs- und Betriebsdaten erheben, lokal aggregieren und in regelmäßigen Abständen an den Hersteller übertragen; die übertragenen Daten sind über Datenbank- und Hardwarekennung dem Betreiber zuordenbar.
Ergebnis: Aggregierte API-Nutzungsdaten werden alle 15 Minuten übertragen.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/Telemetry/ (`TelemetryAggregator`, `HttpTelemetryUploadClient`, `DatabaseGuidProvider`, `HardwareIdProvider`) – Begründung: Vollständige Telemetriekette inkl. Identifikationsmerkmalen.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryFlushService.cs:21 und TelemetryUploadService.cs:33 – Begründung: Konkrete Aggregations- und Übertragungsintervalle.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/WcfBridge/Interception/Interceptors/ApiCallTelemetryInterceptor.cs – Begründung: Erfassung erfolgt querschnittlich bei jedem API-Aufruf.
Prüfidee: Netzwerkverkehr des Web-Service beobachten; innerhalb von 15 Minuten muss genau eine Telemetrieübertragung erfolgen.
Tracelinks: StRS-018, StRS-024
Konsolidierung: nein
Status: belegt; Teilaussage [HYPOTHESE] – welche Inhalte konkret übertragen werden und ob ein Opt-out besteht, ist nicht belegt; siehe HYP-007
```
@@ -0,0 +1,185 @@
# Traceability-Matrix
**System:** c-entron ERP-Suite · **Erstellt:** 2026-08-25
**Bezug:** `StRS.md`, `SyRS.md`, `SwRS.md`
Die Matrix stellt Forward-Traceability (StRS → SyRS → SwRS) und Backward-Traceability
(SwRS → SyRS → StRS) her. Die Spalte *Artefaktbeleg* nennt das jeweils zentrale, in den
Anforderungen als `PRIMÄR` klassifizierte Artefakt der Kette. Ein `—` bedeutet, dass auf der
betreffenden Ebene keine eigenständige Anforderung abgeleitet werden konnte; diese Lücken sind
im `Analysebericht.md`, Abschnitt „Bekannte Lücken", aufgeführt.
Prüfergebnis des maschinellen Konsistenzchecks (siehe `Analysebericht.md`):
**119 Anforderungen, keine doppelten IDs, keine Tracelinks auf nicht existierende IDs, jede
Anforderung mit mindestens einem `PRIMÄR`-Beleg.**
---
## 1. Konsolidierte Matrix
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg |
|---|---|---|---|
| StRS-001 Mandanten-/Filialfähigkeit | SyRS-015 Belegnummernvergabe | SwRS-010 NumberGroup-Entität | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152` |
| StRS-001 | SyRS-015 | SwRS-011 Nummernreservierung | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:62-92` |
| StRS-001 | SyRS-012 Einschränkende Rechte | SwRS-015 Zentrale Belegrechteprüfung | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10295` |
| StRS-002 Rollenbasierte Zugriffssteuerung | SyRS-011 Rechteauflösung über Gruppen | SwRS-016 Rechte-Caching | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:644-664` |
| StRS-002 | SyRS-011 | SwRS-017 Sichtrus/Sichmemb | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:97-101, 653-656` |
| StRS-002 | SyRS-011 | SwRS-018 UserRightsConst | `src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:10-16` |
| StRS-002 | SyRS-012 | SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295` |
| StRS-002 | SyRS-030 Rechte-Audit | SwRS-019 Schutz der Standardrechtestruktur | `src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:348-374, 762-857` |
| StRS-002 | SyRS-011 | SwRS-040 Modulregistrierung | `src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs` |
| StRS-003 Kundenselbstbedienung | SyRS-013 Web-Account-Rechtemodell | SwRS-041 Nexus-Autorisierungsattribute | `src/nexus/CentronNexus/Shared/Authorization/Attributes/` |
| StRS-003 | SyRS-034 Portbasierte Portaltrennung | SwRS-041 | `src/nexus/CentronNexus/Shared/Authorization/PortAuthorization.cs:17-71` |
| StRS-003 | SyRS-003 Anmeldeverfahren | SwRS-042 Nexus-Anmeldung mit Rückfall | `src/nexus/CentronNexus/Shared/Auth/AuthService.cs:49-71` |
| StRS-003 | SyRS-010 Methodenbeschränkung | SwRS-027 Interceptorkette | `…/WcfBridge/Interception/Interceptors/AuthenticateInterceptor.cs:29-48` |
| StRS-004 Lizenzabhängiger Funktionsumfang | SyRS-007 Lizenz-/Kontingentprüfung | SwRS-020 ApplicationKind | `src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:11-53` |
| StRS-004 | SyRS-007 | SwRS-021 LicenseGuids | `src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs` |
| StRS-004 | SyRS-008 Anwendungsrechteprüfung | SwRS-020 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:68-86` |
| StRS-004 | SyRS-009 Access Tokens | SwRS-025 Token-Lizenzkontingent | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs:436-451` |
| StRS-004 | SyRS-027 Schemamigration | SwRS-036 ScriptEngineBL | `src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:219-236` |
| StRS-005 Verkaufsbelegfluss | SyRS-014 Belegzustandsmodell | SwRS-012 ReceiptState | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28` |
| StRS-005 | SyRS-016 Belegversionierung | SwRS-013 Datums-/Versionsvalidierung | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578` |
| StRS-005 | SyRS-016 | SwRS-004 ReceiptBase | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72` |
| StRS-005 | SyRS-018 Rechteprüfung beim Speichern | SwRS-009 SpecificLogics | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3600-3634` |
| StRS-005 | SyRS-016 | SwRS-014 Belegvorlagen | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:65` |
| StRS-005 | SyRS-020 Steuersatzermittlung | SwRS-028 Steuersatzkette | `src/backend/Centron.BL/Warehousing/TaxBL.cs:207-237` |
| StRS-006 Beschaffungsprozess | SyRS-015 | SwRS-010 | `src/backend/Centron.BL/Administration/Company/NumberGroupEnum.cs:40-55, 106-117` |
| StRS-006 | SyRS-019 Lagerbuchung | SwRS-030 Mengendifferenzbuchung | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:212-231` |
| StRS-006 | SyRS-024 EDI-Import | SwRS-046 EDI-Partial-Classes | `src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.*.cs` |
| StRS-007 Vertragsgeschäft | SyRS-022 Vertragsselektion | SwRS-032 Abrechnungslauf und -protokoll | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:820-845, 2101-2118` |
| StRS-007 | SyRS-042 Stapelverarbeitung | SwRS-028 | `…/AutomaticFactura/AutomaticFacturaBL.Contracts.cs:861, 890, 898, 910, 924` |
| StRS-008 Helpdesk | SyRS-035 Ticket-Rechteprüfung | SwRS-043 Feldlängenbegrenzung | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:328-349, 410-466` |
| StRS-008 | SyRS-036 Konfigurierbares Statusmodell | SwRS-044 Kurzbeschreibungspräfix | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:351-393, 433` |
| StRS-009 Servicezeiterfassung | SyRS-035 | SwRS-043 | `src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskCompact.cs:83-90` |
| StRS-010 Lagerbestandsführung | SyRS-019 | SwRS-030 | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:171-236` |
| StRS-010 | SyRS-019 | SwRS-031 IsBooked-Konsistenzprüfung | `…/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:207-210` |
| StRS-011 Elektronische Rechnung | SyRS-023 Formatableitung | SwRS-045 ZUGFeRD-Parametrisierung | `…/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:1285-1289` |
| StRS-012 Buchhaltungsübergabe | SyRS-023 | SwRS-045 | `…/DataExchange/BookKeeping/BookKeepingExportBL.cs:832, 1437, 1560` |
| StRS-013 Mahnwesen | SyRS-037 Mahnstufen und Mahnstopp | SwRS-033 Mahnstufenauswertung | `…/Sales/Receipts/Invoices/Dunning/DunningBL.cs:207-231, 392-431` |
| StRS-014 EDI-Anbindung | SyRS-024 | SwRS-046 | `src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs:23,37` |
| StRS-015 Revisionssicherheit | SyRS-016 | SwRS-007 Versionstabellen | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3595-3634` |
| StRS-015 | SyRS-031 Feldgenaues Belegprotokoll | SwRS-013 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10313-10369` |
| StRS-015 | SyRS-017 Nebenläufigkeitsschutz | SwRS-004 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4939-4940` |
| StRS-016 DSGVO-Betroffenenrechte | SyRS-038 Anonymisierung | SwRS-047 DSGVO-Löschlogik | `…/Administration/DataSecurity/DataSecurityBL.cs:26-27, 787-855` |
| StRS-017 Identitätsanbindung / 2FA | SyRS-003 | SwRS-023 Authenticator-Strategiemuster | `…/Administration/Logins/Auth/AuthenticatorFactory.cs:54-147` |
| StRS-017 | SyRS-004 Kennwortprüfung | SwRS-024 Hashverfahren | `…/Administration/Logins/Auth/BasicAuthenticator.cs:46-50` |
| StRS-017 | SyRS-005 Kontodeaktivierung | SwRS-023 | `…/Administration/Logins/Auth/Authenticator.cs:157-218` |
| StRS-017 | SyRS-006 Zwei-Faktor-Authentifizierung | SwRS-023 | `…/Administration/Logins/TwoFactor/` |
| StRS-018 Hintergrundverarbeitung | SyRS-025 Ausführungsintervalle | SwRS-034 ManagedBackgroundService | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94` |
| StRS-018 | SyRS-026 Steuerung und Resilienz | SwRS-034 | `…/AspNetCore/HostedServices/ManagedBackgroundService.cs:101-157` |
| StRS-018 | SyRS-025 | SwRS-035 Datenqualitätsaufgaben | `…/AspNetCore/HostedServices/DataQualityService.cs:28-71, 183` |
| StRS-018 | SyRS-023 / SyRS-036 | SwRS-038 Einstellungssysteme | `src/backend/Centron.BL/Administration/Settings/AppSettingsConst.cs` |
| StRS-018 | SyRS-043 Telemetrie | — | `src/webservice/Centron.Host/AspNetCore/Telemetry/` |
| StRS-019 Deutsch als Primärsprache | SyRS-028 Zweisprachigkeit | SwRS-051 ResX-Lokalisierung | `LocalizedStrings.resx` / `LocalizedStrings.en.resx`, `ResXManager.config.xml` |
| StRS-020 Online-Banking | SyRS-014 | SwRS-033 | `src/apis/Centron.APIs.FinAPI/FinApiConstants.cs:13-16` |
| StRS-020 | SyRS-037 | SwRS-033 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4920-4958` |
| StRS-021 Belegdruck und PDF-Ablage | SyRS-039 Dublettenvermeidung | — | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3475-3483` |
| StRS-022 Provisionsermittlung | SyRS-018 | — | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvision*.cs` |
| StRS-023 RMA-Abwicklung | SyRS-014 | SwRS-012 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:4152-4180` |
| StRS-024 Verteilte Betriebstopologie | SyRS-040 Topologie | SwRS-048 Technologiebasis | `docker/compose/compose.yaml:1-54` |
| StRS-024 | SyRS-041 Umschaltbarer Datenzugriff | SwRS-001 Schichtenarchitektur | `Centron.sln`, `src/centron/Centron.WPF.UI/Services/` |
| StRS-024 | SyRS-041 | SwRS-002 Doppelimplementierung BL/WS | `src/centron/Centron.WPF.UI/Services/` (688 Dateien) |
| StRS-024 | SyRS-041 | SwRS-003 Result-Fehlermodell | `src/backend/Centron.Interfaces/BL/` |
| StRS-024 | SyRS-027 | SwRS-006 Dualschema Tabellen/Sichten | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs` |
| StRS-024 | SyRS-027 | SwRS-036 Skriptbasierte Migration | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs:40-177` |
| StRS-024 | SyRS-027 | SwRS-037 Idempotente Schemaänderungen | `…/Scripts/ScriptMethods/Scripts/ScriptMethod11803.cs:14-20` |
| StRS-024 | SyRS-027 | SwRS-049 Bau- und Versionierungsvorgaben | `Directory.Build.props:6-43`, `version.json` |
| StRS-024 | SyRS-027 | SwRS-050 CI-/CD-Pipelines | `.github/workflows/`, `azure/` |
| StRS-024 | SyRS-032 Verschlüsselte Geheimnisse | SwRS-039 Konfigurationsserialisierung | `…/WebServiceConfiguration/WebServiceConfigSerializer.cs:30,41,56,88,163` |
| StRS-024 | SyRS-033 Transportverschlüsselung | SwRS-039 | `…/WebServiceConfigSerializer.cs:35-36`, `docker/compose/appsettings.Production.json:24-28` |
| StRS-024 | SyRS-016 | SwRS-008 Legacy-Persistenzpfad | `src/backend/Centron.DAO/Repositories/`, `…/Entities/DbEntities/` |
| StRS-025 Preisfindung | SyRS-021 Vorrangfolge | SwRS-029 Konditionsarten | `…/Sales/Receipts/Internal/ReceiptItemPriceBL.cs:169-266` |
| StRS-002 / StRS-004 | SyRS-001 Ticketauthentifizierung | SwRS-022 Ticketentität | `…/Administration/Logins/Auth/Authenticator.cs:94-155`, `TicketBL.cs:61-94` |
| StRS-002 | SyRS-001 | SwRS-026 ASP.NET-Core-Ticketschema | `src/webservice/Centron.Host/AspNetCore/TicketAuthenticationHandler.cs:38-144` |
| StRS-002 | SyRS-001 | SwRS-027 Interceptorkette | `…/WcfBridge/Interception/Interceptors/` (8 Klassen) |
| StRS-002 | SyRS-002 Ticketlebensdauer | SwRS-022 | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:26-28, 113-164` |
| StRS-002 | SyRS-029 Sicherheitsprotokollierung | SwRS-024 | `…/Auth/BasicAuthenticator.cs:45,55,58,67`, `…/Auth/Authenticator.cs:22-42` |
| StRS-005 | SyRS-014 | SwRS-005 Objekttypschlüssel | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:20-264` |
---
## 2. Rückwärtsverfolgung: SwRS → SyRS → StRS (Kurzform)
| SwRS-ID | Titel | → SyRS | → StRS |
|---|---|---|---|
| SwRS-001 | Schichtenarchitektur | SyRS-041 | StRS-024 |
| SwRS-002 | Doppelimplementierung BL/WS | SyRS-041 | StRS-024 |
| SwRS-003 | Result-Fehlermodell | SyRS-041, SyRS-018 | StRS-024, StRS-002 |
| SwRS-004 | ReceiptBase-Hierarchie | SyRS-014, SyRS-016 | StRS-005 |
| SwRS-005 | CentronObjectKindNumeric | SyRS-031 | StRS-005 |
| SwRS-006 | Dualschema Tabellen/Sichten | SyRS-027 | StRS-024 |
| SwRS-007 | Versionstabellen | SyRS-016 | StRS-015 |
| SwRS-008 | Legacy-Persistenzpfad | SyRS-016 | StRS-024 |
| SwRS-009 | SpecificLogics-Delegation | SyRS-015, SyRS-018 | StRS-005 |
| SwRS-010 | NumberGroup-Entität | SyRS-015 | StRS-001 |
| SwRS-011 | Nummernreservierung | SyRS-015 | StRS-001 |
| SwRS-012 | ReceiptState | SyRS-014 | StRS-005 |
| SwRS-013 | Datums-/Versionsvalidierung | SyRS-016 | StRS-005, StRS-015 |
| SwRS-014 | Belegvorlagen | SyRS-015 | StRS-005 |
| SwRS-015 | Zentrale Belegrechteprüfung | SyRS-012, SyRS-018 | StRS-002 |
| SwRS-016 | Rechte-Caching | SyRS-011 | StRS-002 |
| SwRS-017 | Sichtrus/Sichmemb | SyRS-011 | StRS-002 |
| SwRS-018 | UserRightsConst | SyRS-008, SyRS-011 | StRS-002 |
| SwRS-019 | Schutz der Standardrechtestruktur | SyRS-030 | StRS-002 |
| SwRS-020 | ApplicationKind | SyRS-007, SyRS-008 | StRS-004 |
| SwRS-021 | LicenseGuids | SyRS-007 | StRS-004 |
| SwRS-022 | Ticketentität | SyRS-001, SyRS-002, SyRS-007 | StRS-002, StRS-004 |
| SwRS-023 | Authenticator-Strategiemuster | SyRS-003 | StRS-017 |
| SwRS-024 | Hashverfahren | SyRS-004, SyRS-009, SyRS-032 | StRS-017 |
| SwRS-025 | Token-Lizenzkontingent | SyRS-009 | StRS-004 |
| SwRS-026 | ASP.NET-Core-Ticketschema | SyRS-001, SyRS-009 | StRS-002 |
| SwRS-027 | Interceptorkette | SyRS-001, SyRS-010, SyRS-043 | StRS-002, StRS-003 |
| SwRS-028 | Steuersatzkette | SyRS-020, SyRS-042 | StRS-005, StRS-011 |
| SwRS-029 | Konditionsarten | SyRS-021 | StRS-025 |
| SwRS-030 | Mengendifferenzbuchung | SyRS-019 | StRS-010 |
| SwRS-031 | IsBooked-Konsistenzprüfung | SyRS-019 | StRS-010 |
| SwRS-032 | Vertragsabrechnungslauf | SyRS-022 | StRS-007 |
| SwRS-033 | Mahnstufenauswertung | SyRS-037 | StRS-013 |
| SwRS-034 | ManagedBackgroundService | SyRS-025, SyRS-026 | StRS-018 |
| SwRS-035 | Datenqualitätsaufgaben | SyRS-025, SyRS-026 | StRS-018 |
| SwRS-036 | ScriptEngineBL | SyRS-027 | StRS-024, StRS-004 |
| SwRS-037 | ScriptHelpers | SyRS-027 | StRS-024 |
| SwRS-038 | Einstellungssysteme | SyRS-023, SyRS-036 | StRS-018 |
| SwRS-039 | Konfigurationsserialisierung | SyRS-032, SyRS-033 | StRS-024 |
| SwRS-040 | Modulregistrierung | SyRS-011 | StRS-002, StRS-004 |
| SwRS-041 | Nexus-Autorisierungsattribute | SyRS-013, SyRS-034 | StRS-003 |
| SwRS-042 | Nexus-Anmeldung | SyRS-003 | StRS-003 |
| SwRS-043 | Ticket-Feldlängen | SyRS-035 | StRS-008 |
| SwRS-044 | Ticket-Präfix | SyRS-035, SyRS-036 | StRS-008 |
| SwRS-045 | ZUGFeRD-Parametrisierung | SyRS-023 | StRS-011 |
| SwRS-046 | EDI-Partial-Classes | SyRS-024 | StRS-014 |
| SwRS-047 | DSGVO-Löschlogik | SyRS-038 | StRS-016 |
| SwRS-048 | Technologiebasis | SyRS-040 | StRS-024 |
| SwRS-049 | Bau- und Versionierungsvorgaben | SyRS-027 | StRS-024 |
| SwRS-050 | CI-/CD-Pipelines | SyRS-027 | StRS-024 |
| SwRS-051 | ResX-Lokalisierung | SyRS-028 | StRS-019 |
---
## 3. Konsolidierungskandidaten (modulübergreifende Redundanz)
Die folgende Übersicht fasst alle in den Anforderungen im Feld `Konsolidierung` vermerkten
Kandidaten zusammen. Sie ist die zentrale Arbeitsliste für die Zusammenführung fachlich gleicher
Funktionen im Zielsystem.
| # | Redundanz | Betroffene Anforderungen | Empfehlung für das Zielsystem |
|---|---|---|---|
| K-01 | Zwei getrennte Rechtemodelle (Mitarbeiter über `Sichtrus`/`Sichmemb`, Web-Accounts über `WebAccountsRights`) mit disjunktem Nummernraum | StRS-002, StRS-003, SyRS-011, SyRS-013 | Ein einheitliches Rollen-/Berechtigungsmodell mit Mandanten-, Filial- und Kundenkontext |
| K-02 | Muster „Basisrecht + ONLY_OWN + ONLY_OWN_BRANCH" für 7 Belegarten, Tickets, Kalender, CRM-Projekte und Projektverwaltung dupliziert | SyRS-012 | Generisches, deklaratives Sichtbarkeitskonzept (Datenbereichsfilter) statt Einzelrechte |
| K-03 | Doppelimplementierung jeder Fachfunktion als `BL*Logic` und `WS*Logic` (ca. 688 Clientdateien) | SyRS-041, SwRS-002 | Bei Web-/SaaS-Zielarchitektur entfällt der Direktzugriff; ein Pfad genügt |
| K-04 | Zwei Persistenzpfade für Belege (NHibernate-Entität + `SaveReceipt*Repository` auf Alttabellen) | SwRS-006, SwRS-008 | Ein Persistenzmodell auf einem bereinigten Schema |
| K-05 | Zweischichtiges Datenbankschema (deutsche Alttabellen + englische Sichten) | SwRS-006 | Ein Schema mit durchgängig englischer Benennung |
| K-06 | Drei Hashverfahren für Geheimnisse (SHA-1 ohne Salt, SHA-256, gesalzener Hash) | SyRS-004, SwRS-024 | Ein modernes, gesalzenes Verfahren (PBKDF2/Argon2) für alle Geheimnisse |
| K-07 | Zwei Ticketprüfpfade (WCF-Bridge-Interceptor und ASP.NET-Core-Handler) | SyRS-001, SwRS-026, SwRS-027 | Ein Authentifizierungs-Middleware-Pfad |
| K-08 | Drei Konditionsstrukturen für Sonderpreise (Vertrag, Kunde, Staffel) | StRS-025, SyRS-021, SwRS-029 | Einheitliches Konditionsmodell mit Gültigkeitszeitraum, Preisbasis und Vorrangregel |
| K-09 | Drei Einstellungsschalter für dasselbe E-Rechnungsprofil (`ActiveZugferdInterface`, `IsZugferdXRechnungActive`, `IsXRechung2Active`) | SyRS-023 | Ein Schalter mit Profilliste |
| K-10 | Zwei Anwendungseinstellungssysteme (`Stammdat` und `ApplicationSettings`) | SwRS-038 | Ein typisiertes Einstellungssystem mit Metadaten |
| K-11 | Optimistische Nebenläufigkeitsprüfung an sieben Stellen kopiert | SyRS-017 | Zentrale Kapselung in der Persistenzschicht |
| K-12 | Änderungsprotokoll mit je einer Logmethode pro Feld (`ReceiptLogBL`, 74 KB) | SyRS-031 | Metadatengetriebenes, generisches Änderungsprotokoll |
| K-13 | Rechte-IDs dupliziert in `ApplicationKind.cs`, `WebAccountRightsConst.cs` und `GetAssignableAdminRightI3Ds()` | SyRS-008, SwRS-018 | Eine Quelle für alle Rechtekennungen |
| K-14 | Zwei Textquellen (ResX-Ressourcen und deutsche Quelltextliterale) | StRS-019, SwRS-051 | Ausschließlich Ressourcen, keine Literale |
| K-15 | Zwei Skriptformen für Datenbankmigrationen (C#-Klassen, XML-Sammlungen) | SwRS-036 | Ein Migrationsformat |
| K-16 | Zwei CI-Systeme (GitHub Actions, Azure DevOps) mit teilweise gleichen Aufgaben | SwRS-050 | Ein CI-/CD-System |
| K-17 | Zwei Anzeigetextquellen für `ReceiptState` (`[Description]` und `GetReceiptStateString`), beide nicht lokalisiert | SwRS-012 | Ein lokalisierter Anzeigetext je Zustand |
| K-18 | Sechs strukturgleiche EDI-Leseimplementierungen je Distributor | SwRS-046 | Plug-in-Schnittstelle mit einheitlichem Zwischenformat |
| K-19 | Kunden- und Lieferantenbelege teilen `ReceiptBase`, unterscheiden sich aber in Persistenz und Nummernkreisen | StRS-005, StRS-006 | Einheitliches Belegmodell mit Rollenunterscheidung (Debitor/Kreditor) |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 18 (Lauf L)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:43+02:00
- **Endzeit:** 2026-08-25T20:44:48+02:00
- **Dauer gesamt:** 00:45:05 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:45:04 (`duration_ms`) — API: 00:43:56
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-6bfe`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 256
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/21 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 170 |
| Output-Tokens | 237.695 (davon 24.179 Thinking-Tokens) |
| Cache-Write-Tokens | 522.004 |
| Cache-Read-Tokens | 21.995.319 |
| Agent-Turns | 195 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 170 | 4.192 | 4.362 |
| Output-Tokens | 237.695 | 21 | 237.716 |
| Cache-Write-Tokens | 522.004 | 0 | 522.004 |
| Cache-Read-Tokens | 21.995.319 | 0 | 21.995.319 |
| Tokens gesamt | 22.755.188 | 4.213 | **22.759.401** |
**Tokens gesamt: 22.759.401** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `1054e7e0-425a-4f2c-b765-6da095439081`
- **Permission-Denials:** **1** – 1 x `PowerShell` - `New-Item -ItemType Directory` auf das eigene, bereits vorhandene `Ergebnisse\`-Verzeichnis; von `PowerShell(New-Item:*)` geblockt. Folgenlos, alle 7 Artefakte entstanden.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 59.919 B | 25 Anforderungen |
| `SyRS.md` | 93.621 B | 43 Anforderungen |
| `SwRS.md` | 106.930 B | 51 Anforderungen |
| `Traceability.md` | 18.443 B | 77 Datenzeilen |
| `Hypothesen.md` | 16.868 B | 22 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 21.640 B | Domänenbegriffe |
| `Analysebericht.md` | 24.107 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **119 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,0 % |
| SyRS | 43 | 36,1 % |
| SwRS | 51 | 42,9 % |
| **Gesamt** | **119** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 28 | 23,5 % |
| Sicherheit | 22 | 18,5 % |
| Daten | 15 | 12,6 % |
| Schnittstelle | 6 | 5,0 % |
| Architektur | 6 | 5,0 % |
| Sicherheit / Compliance | 3 | 2,5 % |
| nicht-funktional (ISO 25010: Performanz-Effizienz) | 3 | 2,5 % |
| Sicherheit / nicht-funktional (ISO 25010: Sicherheit) | 2 | 1,7 % |
| Schnittstelle / Sicherheit | 2 | 1,7 % |
| Daten / funktional | 2 | 1,7 % |
| (27 weitere) | 30 | 25,2 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 378 |
| davon `PRIMÄR` | 271 (71,7 %) |
| davon `SEKUNDÄR` | 37 (9,8 %) |
| davon `KONTEXT` | 70 (18,5 %) |
| Belege je Anforderung (Median) | 3 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 119 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 112 | 94,1 % |
| als `HYPOTHESE` gekennzeichnet | 7 | 5,9 % |
| als Workaround vermerkt | 29 | 24,4 % |
| Konsolidierungskandidaten | 30 | 25,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (54 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 119 von 119 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(256 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2636391,"num_turns":195,"stop_reason":"end_turn","session_id":"1054e7e0-425a-4f2c-b765-6da095439081","total_cost_usd":22.1652215,"usage":{"input_tokens":170,"cache_creation_input_tokens":522004,"cache_read_input_tokens":21995319,"output_tokens":237695,"output_tokens_details":{"thinking_tokens":24179},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":522004,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1283,"cache_read_input_tokens":542364,"cache_creation_input_tokens":576,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":576},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":21,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0042970000000000005,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":170,"outputTokens":237695,"cacheReadInputTokens":21995319,"cacheCreationInputTokens":522004,"webSearchRequests":0,"costUSD":22.1609245,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[{"tool_name":"PowerShell","tool_use_id":"toolu_01YW7YLKyVN5QigJvq36TXar","tool_input":{"command":"$p=\"c:\\DEV\\MasterArbeit\\Versuche\\Versuch_01\\01_Lauf_2026-08-25_195915_opus5_solo_v3.6.0-6bfe\\Ergebnisse\"; if(-not (Test-Path $p)){ New-Item -ItemType Directory -Force $p | Out-Null }; Get-ChildItem $p | Format-Table -AutoSize","description":"Ensure output directory exists"}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Die Codebasis ist unverändert (`git status` leer), alle sieben Ergebnisdateien liegen im vorgegebenen Ausgabeverzeichnis.\n\n## Ergebnis\n\n**119 Anforderungen** auf drei Ebenen, jede mit mindestens einem `PRIMÄR`-Beleg:\n\n| Datei | Inhalt | Umfang |\n|---|---|---|\n| `StRS.md` | 25 Stakeholder-Anforderungen + Akteurstabelle | 58 KB |\n| `SyRS.md` | 43 Systemanforderungen (Auth/Lizenz, Rechte, Belege, Schnittstellen, Betrieb) | 91 KB |\n| `SwRS.md` | 51 Softwareanforderungen (Architektur, Datenmodell, Fachlogik, Betriebskomponenten) | 104 KB |\n| `Traceability.md` | Vorwärts-/Rückwärtsmatrix + 19 verdichtete Konsolidierungskandidaten | 18 KB |\n| `Hypothesen.md` | 12 Hypothesen mit fehlender Information und offener Frage | 16 KB |\n| `Glossar.md` | 7 Begriffsgruppen mit technischer Entsprechung und Beleg | 21 KB |\n| `Analysebericht.md` | Komponentenübersicht, Analysetiefe, Konsistenzcheck, Selbstbewertung | 23 KB |\n\n**Konsistenzcheck (maschinell ausgeführt):** keine doppelten IDs, keine Anforderung ohne Beleg, keine Tracelinks auf nicht existierende IDs, jede SwRS referenziert eine SyRS, jede SyRS eine StRS. Belegverteilung: 271 `PRIMÄR` / 37 `SEKUNDÄR` / 70 `KONTEXT` (71,7 % primär).\n\n**Zwei Punkte, die für die Validierung hervorstechen:**\n\n1. Die Entwicklerdokumentation unter `docs/` habe ich durchgängig als `KONTEXT` klassifiziert, nicht als `PRIMÄR` — sie widerspricht dem Code nachweisbar beim Belegzustandsmodell (Doku: vier Zustände „Draft/Released/Processed/Cancelled\", Code: drei Zustände `Active/Completed/Canceled`). Dokumentiert als W-01 und HYP-009.\n\n2. 29 Anforderungen tragen `Status: … Workaround`. Die sieben kritischsten sind im Analysebericht priorisiert, darunter ungesalzenes SHA-1 für Benutzerkennwörter (mit `// TODO the password should be salted!!!` im Quelltext), die unvollständige DSGVO-Löschung (`NotImplementedException` für Kunden-, Lieferanten- und Account-Stammsätze) und der doppelte Belegpersistenzpfad.\n\n**Zur Einordnung der Abdeckung:** Die architektur- und sicherheitsprägenden Mechanismen sind weitgehend vollständig erfasst; die fachliche Breite schätze ich auf etwa ein Drittel. Nicht analysiert blieben u. a. Statistik/Auswertung, Passwortmanager, Telefonie, KI-Modul und die Fremd-API-Anbindungen — vollständig aufgelistet in Abschnitt 2 des Analyseberichts. Der wirkungsvollste Nachschlag wäre ein Datenbankschema-Abzug: er lag nicht vor und ist die Hauptursache der verbliebenen `KONTEXT`-Belege im Datenmodellbereich.","ttft_ms":1763,"ttft_stream_ms":1017,"time_to_request_ms":46,"type":"result","duration_ms":2703563,"uuid":"3f298d5f-7cdd-426f-9822-eb84d7f82386","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,0 % |
| SyRS | 43 | 36,1 % |
| SwRS | 51 | 42,9 % |
| **Gesamt** | **119** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 28 | 23,5 % |
| Sicherheit | 22 | 18,5 % |
| Daten | 15 | 12,6 % |
| Schnittstelle | 6 | 5,0 % |
| Architektur | 6 | 5,0 % |
| Sicherheit / Compliance | 3 | 2,5 % |
| nicht-funktional (ISO 25010: Performanz-Effizienz) | 3 | 2,5 % |
| Sicherheit / nicht-funktional (ISO 25010: Sicherheit) | 2 | 1,7 % |
| Schnittstelle / Sicherheit | 2 | 1,7 % |
| Daten / funktional | 2 | 1,7 % |
| (27 weitere) | 30 | 25,2 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 378 |
| davon `PRIMÄR` | 271 (71,7 %) |
| davon `SEKUNDÄR` | 37 (9,8 %) |
| davon `KONTEXT` | 70 (18,5 %) |
| Belege je Anforderung (Median) | 3 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 119 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 112 | 94,1 % |
| als `HYPOTHESE` gekennzeichnet | 7 | 5,9 % |
| als Workaround vermerkt | 29 | 24,4 % |
| Konsolidierungskandidaten | 30 | 25,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (54 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 119 von 119 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195915_opus5_solo_v3.6.0-6bfe\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:44:48.7401722+02:00
@@ -0,0 +1 @@
2026-08-25T19:59:43.6861284+02:00
@@ -0,0 +1,281 @@
# Analysebericht
**System:** NEXOWARE c-entron ERP
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse ohne Ausführung
**Analysebasis:** `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48`, Branch `main`
**Iteration:** V1 Baseline (Prompt-only), Lauf 01 · **Werkzeugkonfiguration:** Claude Code ohne Agentendateien, ohne MCP-Server
**Erstellt:** 2026-08-25
---
## 1. Umfang des Untersuchungsgegenstands
Die Codebasis wurde vollständig erhoben und quantifiziert:
| Kennzahl | Wert |
|---|---|
| Projekte in `Centron.sln` | 44 |
| C#-Quelldateien (ohne `bin`/`obj`) | 14 782 (67,4 MB) |
| XAML-Dateien | 1 233 (15,8 MB) |
| Razor-Dateien (Blazor) | 491 (4,2 MB) |
| CSS-Dateien | 264 · JS 40 · XML 28 · JSON 16 · YAML/YML 26 · resx 14 |
| Markdown-Dokumentation | 50 Dateien (`docs/`: 44 Sachdateien) |
| Commits in der Historie | 52 135 |
| NHibernate-Entitätsdateien | 1 179 |
| NHibernate-Zuordnungsdateien | 983 |
| Datenbank-Migrationsskripte | 764 |
| Anwendungseinstellungen (`ApplicationSettingID`) | 492 |
| Anwendungseinstellungen (`AppSettingsConst`, Legacy) | 728 |
| Legacy-REST-Methoden | 2 599 (davon 2 374 mit `[Authenticate]`) |
| Moderne REST-Endpunkte | 160 in 42 Controllern |
| Registrierte Client-Module | 84 in 15 Modulgruppen |
| Hintergrunddienste | 35 |
| Benutzerrechte (`UserRightsConst`) | über 900 Konstanten |
| Lizenz-GUIDs | 159 |
| Anmeldefähige Anwendungsarten | 44 |
| Objektarten (`CentronObjectKindNumeric`) | 205 |
| Testprojekte | 12 (378 C#-Dateien) |
**Keine SQL-Dateien im Repository.** Das Datenbankschema existiert ausschließlich als C#-Migrationsskripte (`ScriptMethod*.cs`) und FluentNHibernate-Zuordnungen. Eine vollständige Schemarekonstruktion war in dieser Iteration nicht Gegenstand der Analyse.
**Zielplattform:** .NET 10 (`global.json`: SDK 10.0.100). `Centron.BL` mit Multi-Targeting `net10.0;net10.0-windows`; Web-Service und Datenzugriff plattformneutral (`net10.0`); nur der WPF-Client ist Windows-gebunden. Produktversion laut `version.json`: `2.0.2611-alpha`.
---
## 2. Modul- und Komponentenübersicht
### 2.1 Ausführungseinheiten
| Einheit | Projekt(e) | Rolle |
|---|---|---|
| Windows-Fachclient | `Centron.WPF.UI`, `Centron.WPF.UI.Extension` | Vollständige ERP-Bedienoberfläche (WPF/DevExpress) |
| Web-Service | `Centron.Host` + `Centron.Host.Console` / `.WindowsService` | Zentrale Server-API, 35 Hintergrunddienste, Lizenz- und Sitzungsverwaltung |
| Moderne API | `Centron.Controllers` | Versionierte ASP.NET-Core-REST-Schnittstelle |
| Webportal | `CentronNexus`, `CentronNexus.Host` | Blazor-Server (ServiceBoard, WebCart, WebOffer, C-Sign) |
| Outlook-Erweiterung | `CentronNexus.OutlookAddIn` | Office-Add-In für CRM-, Ticket- und Belegzugriff |
| Konfigurationswerkzeug | `c-entron.misc.ConnectionManager` | Erzeugung der `WebServiceConfig.xml` (nur Windows) |
| Gemeinsame Schichten | `Centron.BL`, `Centron.DAO`, `Centron.Entities`, `Centron.Interfaces`, `Centron.Common`, `Centron.Gateway`, `Centron.Core`, `Centron.Controls` | Fachlogik, Persistenz, Datenmodell, Verträge, Hilfsfunktionen, Format-Gateways, gemeinsame Steuerelemente |
| Externe Integrationen | `src/apis/` (7 Projekte), `Centron.Api.docuFORM` | ITscope, Icecat, COP, EGIS, FinAPI, GLS, Shipcloud, docuFORM |
### 2.2 Fachliche Modulgruppen des Clients (15 Gruppen, 84 Module)
Abrechnung · Administration · Adressen/CRM · Automatisierung · Buchhaltung/Finanzen · Controlling/Analytics · Einkauf · Helpdesk · Hilfe · Logistik · MyCentron · Passwort Manager (abgekündigt) · Produktion · Stammdaten · Verträge
### 2.3 Fachlogik nach Größe (`Centron.BL`)
| Bereich | Dateien | Größte Einzelkomponente |
|---|---|---|
| Administration | 959 | `ScriptMethodsCollection.cs` (714 KB), `AppSettingsGroupBL.cs` (153 KB) |
| WebServices (DTO-Wandlung) | 464 | `ReceiptWebServiceBL.cs` (239 KB) |
| Sales | 248 | `ReceiptBL.cs` (609 KB), `ReceiptItemBL.cs` (225 KB) |
| Warehousing | 40 | `ArticleBL.cs` (206 KB), `ArticleImportBL.cs` (139 KB) |
| Accounts | 29 | `AccountWebServiceBL.cs` (121 KB) |
| EDI | 27 | `SupplierEdiBL.cs` (118 KB) |
| ReportEngine | 26 | `ReportDataBL.cs` (92 KB) |
| ArtificialIntelligence | 25 | – |
| DataExchange | 23 | `InvoiceZugferdBL.cs` (120 KB), `BookKeepingExportBL.cs` (81 KB) |
| Statistics | 16 | `ContractEvaluationBL.cs` (87 KB) |
---
## 3. Analysetiefe je Bereich
Die Analysetiefe wurde risikobasiert priorisiert: Sicherheits-, Abrechnungs- und Berechtigungslogik zuerst, danach Belegverarbeitung und Datenmodell, zuletzt Betriebs- und Bauartefakte.
**Legende:** ● vollständig gelesen · ◐ gezielt gelesen (Schlüsselstellen im Detail, Rest über Struktur/Signaturen) · ○ nur strukturell erfasst (Dateibaum, Klassennamen, Größen) · – nicht analysiert
| Bereich | Tiefe | Was konkret gelesen wurde | Anforderungen |
|---|---|---|---|
| **Authentifizierung / Sitzung** | ● | `Authenticator.cs`, `AuthenticatorFactory.cs`, `BasicAuthenticator.cs`, `WebAccountAuthenticator.cs`, `TicketBL.cs`, `TwoFactorAuthBL.cs`, `JwtAuthController.cs` — vollständig | SyRS-001…008, SwRS-025, SwRS-026 |
| **Autorisierung / Rechtemodell** | ● | `AppRightsBL.cs` (vollständig), `UserRightsConst.cs` (Hierarchieteil vollständig, Konstantenblock stichprobenhaft), `AuthorizeUserRightAttribute.cs`, `Authorization/README.md`, `CentronRights.md` | StRS-002, SyRS-009…014, SwRS-002, SwRS-003, SwRS-040 |
| **Lizenzierung** | ● | `LicenseManager.cs` (vollständig), `ApplicationKind.cs` (vollständig), `LicenseGuids.cs` (Kopfteil + Auszählung) | StRS-004, SyRS-007, SyRS-008, SwRS-005 |
| **Belegverarbeitung (Kern)** | ◐ | `ReceiptBL.cs`: ca. 1 100 der 12 500 Zeilen im Detail (Speicherpfad 3517–3868, Versionierung 3063–3175, Nummernvergabe 7257–7285, Limitprüfung 8636–8712, Mindestpreis 9036–9124, Abschluss 9753–9803, Rechteprüfungen 10194–10312); Rest über Methodensignaturen | StRS-005, SyRS-016…024, SwRS-006…010 |
| **Belegzustand / Objektarten** | ● | `ReceiptState.cs`, `ReceiptBase.cs`, `CentronObjectKindNumeric.cs` — vollständig | SyRS-016, SwRS-004, SwRS-006 |
| **Lager / Artikelbuchung** | ◐ | `ReceiptArticleBookingBL.cs` (Buchungs- und Rechtelogik im Detail), `ArticleBL.cs` (Rechteermittlung), Struktur `Warehousing/` | StRS-008, SyRS-025, SwRS-013 |
| **Ticket / Helpdesk** | ◐ | `HelpdeskBL.cs` (Rechte-, Längen- und Präfixlogik im Detail), Struktur `Sales/Support/` (53 Klassen) | StRS-007, SyRS-026, SyRS-027, SwRS-011, SwRS-012 |
| **Vertrag / Abrechnung** | ◐ | Abrechnungs-Aufzählungen vollständig; `AutomaticFacturaWebServiceBL.cs` (RMM-Prüfung, `CreateInvoiceToContractComplete` Kopfteil); `contracts-backend.md` vollständig | StRS-006, StRS-021, SyRS-029, SwRS-014 |
| **E-Rechnung (ZUGFeRD/XRechnung)** | ◐ | `InvoiceZugferdBL.cs` Zeilen 52–242 im Detail; Generatorteil strukturell | StRS-012, SyRS-030, SwRS-015 |
| **DSGVO / Datenschutz** | ◐ | `DataSecurityBL.cs`: Rechteprüfungen und zwei Anonymisierungsroutinen im Detail; SQL-Referenzblöcke gesichtet | StRS-013, SyRS-028, SwRS-016 |
| **Änderungsprotokollierung** | ● | `ChangeTrackingEventListener.cs` — vollständig | SyRS-046, SwRS-017 |
| **Hintergrunddienste** | ◐ | `ManagedBackgroundService.cs` vollständig; alle 35 Dienstklassen nach Name und Intervall erfasst; `DataQualityService.md` vollständig | StRS-025, SyRS-035, SyRS-045, SwRS-029 |
| **Schnittstellen (REST)** | ◐ | `AuthenticateAttribute.cs` vollständig; alle `ICentronRestService*.cs` maschinell ausgezählt (Attribute, Verben, Lücken); `ICentronRestService.Receipts.cs` als Muster gelesen; 42 Controller nach Namen und Verbanzahl erfasst | SyRS-010, SyRS-011, SyRS-031, SwRS-030 |
| **Nummernvergabe** | ● | `NumberGroupBL.cs` — vollständig | SyRS-018, SwRS-032 |
| **Konfiguration / Einstellungen** | ◐ | `WebServiceConfig.xml`, `appsettings.json`, `Directory.Build.props`, `global.json`, `version.json`, `compose.yaml` vollständig; `ApplicationSettingID.cs` Kopfteil + Auszählung; `settings-management.md` vollständig | StRS-024, SyRS-049, SwRS-028, SwRS-034 |
| **Betrieb / Deployment** | ◐ | Docker-Verzeichnis vollständig; WiX-Projekte strukturell; `web-service-on-linux.md` vollständig | StRS-019, SyRS-039…041, SwRS-023, SwRS-033 |
| **Datenmodell / Persistenz** | ○ | Verzeichnisstruktur und Dateizahl erfasst; Konventionen aus `database-conventions.md` und `script-rules.md`; `AssetHeadDAO` **nicht** gelesen | SwRS-018, SwRS-039, SwRS-007, SwRS-008 |
| **Lokalisierung** | ○ | Alle `.resx` nach Pfad und Größe erfasst; Inhalte nicht gelesen | StRS-018, SyRS-048, SwRS-022 |
| **Client-Oberfläche (WPF)** | ○ | Verzeichnisstruktur, `ModuleRegistration.cs` (Kopfteil + alle 84 Registrierungen ausgelesen); keine einzelne View/ViewModel im Detail | StRS-001, SyRS-015, SwRS-036 |
| **Webportal (Blazor)** | ○ | Verzeichnisstruktur und Dateizahlen; `appsettings.json` vollständig; `DocumentSigning`-Komponenten nach Namen; keine `.razor`-Datei im Detail | StRS-011, StRS-023, SyRS-037, SyRS-038, SwRS-027 |
| **EDI** | ○ | Partialklassenstruktur, Gateway-Bibliotheken, `edi-architecture.md` vollständig; **keine** Parserimplementierung gelesen | StRS-009 |
| **Externe Integrationen (`src/apis/`)** | ○ | Projekt- und Ordnerstruktur; Anbieterklassen der Artikelsuche nach Namen | StRS-020, SyRS-034, SwRS-024 |
| **Statistik / Reporting** | ○ | Verzeichnisstruktur und Dateigrößen; Rechteblock vollständig | StRS-017, SwRS-021 |
| **Provision** | ○ | Entitätsnamen, Komponentennamen, Rechteblock | StRS-016, SwRS-020 |
| **Finanzen / Mahnwesen / Buchhaltungsexport** | ○ | `DunningLevel.cs` vollständig; `DunningBL.cs`, `DunningRunBL.cs`, `BookKeepingExportBL.cs` nur nach Name und Größe | StRS-010, SyRS-024 |
| **Telemetrie** | ○ | Dienst- und Entitätsnamen; **Inhalt nicht gelesen** | SwRS-037 (HYPOTHESE) |
| **Künstliche Intelligenz (`Centron.BL/ArtificialIntelligence`, 25 Dateien)** | – | nicht analysiert | – |
| **Produktion / PLM** | – | nur als Modulname erfasst | – |
| **Passwort-Manager** | – | nur als Modul- und Rechtename erfasst | – |
| **TAPI / Telefonie** | – | nur als Modul-, Dienst- und Rechtename erfasst | – |
| **MyDay / TaskManager / Kalender** | – | nur als Modul- und Dienstname erfasst | – |
| **Skriptmethoden (764 Migrationsskripte)** | – | nur ausgezählt; kein einzelnes Skript gelesen | – |
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde maschinell über die drei Spezifikationsdateien ausgeführt (Auswertung der Felder `ID`, `Belege`, `Prüfidee`, `Status`, `Tracelinks`).
| Prüfung | Ergebnis |
|---|---|
| **Anzahl Anforderungen** | 114 (25 StRS, 49 SyRS, 40 SwRS) |
| **Doppelte oder mehrfach vergebene IDs** | **keine** |
| **Anforderungen ohne Beleg** | **keine** (0 von 114) |
| **Anforderungen ohne `PRIMÄR`-Beleg** | **keine** (0 von 114) — die Belegpflicht der risikobasierten Priorisierung (Sicherheit, Abrechnung, Berechtigungen) ist damit für alle Anforderungen erfüllt |
| **Anforderungen ohne Prüfidee** | **keine** |
| **Anforderungen ohne Statusfeld** | **keine** |
| **Tracelinks auf nicht existierende IDs** | **keine** |
| **StRS ohne SyRS-Verweis** | keine |
| **SyRS ohne StRS-Verweis** | keine |
| **SyRS ohne SwRS-Verweis** | keine |
| **SwRS ohne SyRS-Verweis** | keine |
| **SwRS ohne direkten StRS-Verweis** | keine |
| **Belege gesamt** | 421 (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`) |
| **Durchschnitt `PRIMÄR`-Belege je Anforderung** | 2,75 |
| **Als `[HYPOTHESE]` gekennzeichnet** | 6 |
| **Mit Zusatz `Workaround` im Feld `Status`** | 18 |
### 4.1 Im Verlauf gefundene und behobene Inkonsistenzen
Beim ersten Konsistenzdurchlauf traten sieben fehlerhafte Tracelinks auf, die bereits korrigiert sind und hier zur Nachvollziehbarkeit dokumentiert werden:
1. **StRS-001 bis StRS-025:** Die Tracelinks waren zunächst gegen eine vorläufige SyRS-Nummerierung gesetzt und zeigten nach der endgültigen Nummerierung auf inhaltlich unpassende Anforderungen. Alle 25 wurden gegen die tatsächlichen Inhalte geprüft und neu gesetzt.
2. **Fehlende SyRS-Ebene für vier Themen:** Änderungsprotokollierung, Rechteänderungsprotokoll, Sprachvorgabe und Anwendungseinstellungen hatten keine Entsprechung auf Systemebene; die StRS verwies deshalb direkt auf die SwRS-Ebene. Ergänzt als **SyRS-046, SyRS-047, SyRS-048, SyRS-049**.
3. **SyRS-034 → SwRS-012:** verwies auf „Konfigurierbare Ticketzustände" statt auf die Integrationskomponenten. Korrigiert auf SwRS-015, SwRS-024.
4. **SyRS-037 → SwRS-014** und **SyRS-038 → SwRS-014:** Portal-Grenzwerte verwiesen auf die Vertragsabrechnung. Korrigiert auf SwRS-034 bzw. SwRS-038.
5. **SyRS-042 → SwRS-032:** E-Mail-Schutz verwies auf die SQL-Verkettung. Korrigiert auf SwRS-035 (Build-Vorgaben, DEBUG-/RELEASE-Unterscheidung).
6. **SyRS-044:** Titel nannte „acht Testprojekte", der Beleg 12. Titel korrigiert.
7. **SwRS-017, SwRS-022, SwRS-028:** verwiesen auf SyRS-036 (Protokollierung) statt auf die jeweils zutreffende neue SyRS-Anforderung. Korrigiert.
### 4.2 Verbleibende Einschränkung
Die Verweise sind **vollständig, aber nicht durchgängig spiegelbildlich**: Ein Verweis ist teils nur in der einen, teils nur in der anderen Anforderung notiert. `Traceability.md` löst dies auf, indem beide Matrizen die Vereinigung aus Vor- und Rückwärtsverweisen bilden. Die vollständige Spiegelung in den Quelldokumenten ist für eine Folge-Iteration vorgemerkt.
---
## 5. Selbstbewertung
### 5.1 Vollständig analysierte Bereiche
Für diese Bereiche liegt eine Anforderungsableitung vor, die den gesamten Entscheidungsraum des Codes abbildet — nicht nur Stichproben:
- **Authentifizierung und Sitzungsverwaltung.** Alle sechs Authentifikator-Implementierungen, die Verfahrenswahl, die Sperrprüfung, die Ticketlebensdauer und die Zwei-Faktor-Logik sind vollständig erschlossen. Der Nachweis der ungesalzenen SHA-1-Kennwortspeicherung ist eindeutig.
- **Rechtemodell.** `AppRightsBL` vollständig; das Datenmodell (`Sichrech`/`Sichgrup`/`Sichtrus`/`Sichmemb`/`Sichbenu`), die Hierarchieauflösung, der Administratorschutz, die Standardrechtestruktur und das Rechteänderungsprotokoll sind belegt.
- **Lizenzierung.** Lizenzprüfung, Anwendungsarten, Ticketzählung, Modulsichtbarkeit und der Zusammenhang „keine Datenbankaktualisierung ohne Lizenz" sind vollständig nachgezeichnet.
- **Belegzustandsmodell und Objektartsystematik.** Abschließend belegt.
- **Nummernvergabe.** Vollständig, einschließlich Nebenläufigkeitssicherung und Lückenprüfung.
- **Änderungsprotokollierung.** Vollständig, einschließlich der beiden Abbruchbedingungen.
- **Betriebsmodell der Hintergrunddienste.** Vollständig; die Basisklasse regelt alle 35 Dienste einheitlich.
### 5.2 Stichprobenhaft analysierte Bereiche
- **`ReceiptBL.cs`** — die zentrale Belegkomponente mit 609 KB. Gelesen wurden rund 9 % der Zeilen, gezielt an den Stellen mit Geschäftsregelcharakter. Die 46 Einzelprüfungen der Speichersequenz sind namentlich und in ihrer Reihenfolge erfasst, aber nur sieben davon inhaltlich analysiert (`CheckIfCustomerLimitIsReached`, `CheckArticleMinPrices`, `CheckExternalInvoiceNumberAlreadyUsed`, `CheckForDuplicatePurchaseOrderNumber`, `TryAutomaticallyCloseReceipt`, `CanUser*`-Familie, `UpdateReceiptNumber`). **Das ist die größte inhaltliche Lücke dieser Iteration.**
- **Helpdesk, Vertragsabrechnung, DSGVO, E-Rechnung, Lagerbuchung.** Jeweils die geschäftsregelrelevanten Methoden gelesen, der übrige Code strukturell erfasst.
- **Schnittstellen.** Vollständig ausgezählt und in ihrer Systematik belegt, aber nur eine Partialdatei inhaltlich gelesen. Aussagen über einzelne Endpunkte sind nur für die namentlich genannten belastbar.
### 5.3 Nicht analysierte Bereiche
Diese Bereiche sind im Anforderungssatz **nicht** oder nur als Modulname vertreten:
| Bereich | Umfang | Begründung der Zurückstellung |
|---|---|---|
| Künstliche Intelligenz | 25 BL-Klassen, 5 Rechte, eigener Controller, `ArtificialIntelligenceChatsController` | Neuer Funktionsbereich ohne erkennbare Kopplung an die Kernprozesse; niedrige Migrationspriorität |
| Produktion / PLM | 2 BL-Klassen, `ProductionOrderManagement` im Portal, `PlmImportService` | Kleiner Umfang, klar abgegrenzt |
| Passwort-Manager | 10 Entitäten, 6 BL-Klassen, eigener Rechteblock, eigene Lizenz | Eigenständiges Zusatzprodukt |
| TAPI / Telefonie | `TapiServer`-Anwendungsart, `TapiClientHub`, `Telephony`-Steuerelemente | Technische Integration ohne ERP-Kernbezug |
| MyDay / TaskManager / Kalender / ToDo | 11 + 20 + Kalender-BL (`ScheduleBL.cs`, 128 KB) | Umfangreich, aber ohne Berührung der risikopriorisierten Themen |
| Mailings / SocialMedia / VideoPortal / DocuBoard | je 1–13 Klassen | Randbereiche |
| SelfCare (`SelfCareWebserviceBL.cs`, 137 KB) | 10 BL-Klassen, eigene Objektarten | Umfangreich; im Zusammenhang mit den anonymen REST-Endpunkten sicherheitsrelevant |
| 764 Migrationsskripte | – | Für Anforderungen nicht auswertbar; relevant nur für eine Schemarekonstruktion |
| Report-Engine (Berichtsdefinitionen) | 26 BL-Klassen, `Centron.Interfaces/CentronReportEngine` | Darstellungsschicht |
### 5.4 Stellen mit dünner Belegdecke
22 der 114 Anforderungen (19 %) haben mindestens so viele `SEKUNDÄR`- und `KONTEXT`-Belege wie `PRIMÄR`-Belege. Neun Anforderungen stützen sich auf genau einen `PRIMÄR`-Beleg. Die kritischsten Fälle:
| Anforderung | Belegverhältnis | Bewertung |
|---|---|---|
| **SwRS-007** (Zweigleisige Belegpersistenz) | 1 PRIMÄR / 3 KONTEXT | Die Aussage über den Schreibpfad (`SaveReceipt*Repository`, `SynchronizeReceiptData`) stützt sich überwiegend auf `receipts-backend-architecture.md`. Der `PRIMÄR`-Beleg belegt nur die **Existenz** der temporären Legacy-Entitäten, nicht ihren Einsatz im Speicherpfad. **Diese Anforderung beschreibt die aufwendigste Struktur der gesamten Belegverarbeitung und ist am schwächsten belegt.** |
| **SwRS-008** (Versionstabellen) | 1 PRIMÄR / 2 KONTEXT | Die Kopiermechanik (`AssetHeadDAO.SaveAssetVersion`, `DoGetFieldList()`) wurde nicht gelesen. |
| **SyRS-044** (Testabdeckung) | 1 PRIMÄR / 3 KONTEXT | Der Umfang ist ausgezählt; die Aussage zur Teststrategie stammt aus der Dokumentation. |
| **SyRS-039** (DB-Strukturaktualisierung) | 2 PRIMÄR / 2 KONTEXT | Die Idempotenzforderung ist eine Projektregel; kein einzelnes Skript wurde auf Einhaltung geprüft. |
| **SwRS-018** (Datenmodellkonventionen) | 2 PRIMÄR / 2 KONTEXT | Konventionen stammen aus der Dokumentation; keine Stichprobe an tatsächlichen Tabellen. |
| **SwRS-036** (MVVM-Struktur) | 2 PRIMÄR / 2 KONTEXT | Struktur belegt, Einhaltung nicht geprüft (keine View im Detail gelesen). |
| **SyRS-032** (Dualer Client-Datenzugriff) | 1 PRIMÄR / 2 KONTEXT | Das Muster ist über den Dateibaum belegt; die Vollständigkeit („jedes Modul implementiert beide") ist Projektregel, nicht nachgewiesen. |
| **SyRS-042** (E-Mail-Schutz) | Kernaussage nur KONTEXT | Als `[HYPOTHESE]` gekennzeichnet; `DeveloperSecurity.cs` nicht auffindbar. |
**Bewertung:** Die dünnen Stellen liegen systematisch dort, wo die Projektdokumentation umfangreich ist und deshalb als Einstieg diente — Persistenzarchitektur, Datenmodellkonventionen, Teststrategie, Architekturmuster. Das ist ein methodisches Muster dieser Iteration, kein Zufall: Wo `docs/` eine fertige Beschreibung liefert, sinkt der Anreiz zur Codeverifikation. Für die Validierung bedeutet das, dass gerade die architekturbeschreibenden Anforderungen (SwRS-001, SwRS-007, SwRS-008, SwRS-018, SwRS-036) am ehesten von der Realität abweichen können.
### 5.5 Belastbarkeit für eine Neuimplementierung
| Bereich | Belastbarkeit | Begründung |
|---|---|---|
| Authentifizierung, Autorisierung, Lizenzierung | **hoch** | Vollständig gelesen, dichte `PRIMÄR`-Belege, Entscheidungsräume abschließend erfasst |
| Belegzustand, Versionierung, Nummernvergabe | **hoch** | Regeln vollständig, mit Fehlermeldungstexten und Randfällen |
| Kreditlimit, Mindestpreis, negative Lagerbuchung, Mahnstufensperre | **hoch** | Vollständige Regeln inkl. Ausnahmen und Übersteuerungspfaden |
| DSGVO, Änderungsprotokollierung | **hoch** | Verarbeitungsschritte feldgenau belegt |
| Belegvalidierung insgesamt | **mittel** | Alle 46 Prüfungen benannt, 7 inhaltlich erschlossen |
| Vertragsabrechnung, E-Rechnung, Ticketverarbeitung | **mittel** | Kernregeln belegt, Detailverhalten offen |
| Persistenzarchitektur | **mittel bis niedrig** | Struktur bekannt, Mechanik nur dokumentationsgestützt |
| EDI, externe Integrationen, Statistik, Provision, Finanzen | **niedrig** | Nur Struktur- und Rechteebene; keine Verarbeitungsregeln |
| KI, Produktion, Passwort-Manager, Telefonie, MyDay, SelfCare | **nicht abgedeckt** | Für diese Bereiche liegt keine Anforderung vor |
---
## 6. Erkenntnisse mit unmittelbarem Handlungsbedarf
Unabhängig von der Neuimplementierung ergaben sich drei Befunde am **laufenden System**:
1. **221 Legacy-REST-Methoden ohne Authentifizierungsmarker** (SyRS-011, Hypothese H-01). Darunter schreibende Operationen wie `DeleteLogo`, `SaveCustomerSpecialArticle` und `DeleteContractExternalArticleImportHead`. Ob ein impliziter Schutz greift, ist ohne Laufzeitprüfung nicht entscheidbar. **Höchste Priorität.**
2. **Ungesalzene SHA-1-Kennwortspeicherung** für Mitarbeiter- **und** Portalkonten (SwRS-026, Hypothese H-02). Der Ist-Zustand ist durch `PRIMÄR`-Belege eindeutig; der Quelltext enthält den Kommentar `// TODO the password should be salted!!!`. Das Kennwort ist zudem Teil der Datenbankabfrage, ein Vergleich in konstanter Zeit findet nicht statt.
3. **Bekannte NuGet-Schwachstellen brechen den Build bewusst nicht ab** (SyRS-043). `Directory.Build.props` nimmt `NU1901`–`NU1904` ausdrücklich von `TreatWarningsAsErrors` aus. Zusätzlich ist `EnableUnsafeBinaryFormatterSerialization` aktiviert.
Ergänzend sind zwei bereits in der Projektdokumentation benannte offene Punkte bestätigt: das Zertifikatskennwort steht im Klartext in `WebServiceConfig.xml`, und die Skriptnummernvergabe erfolgt über eine repository-externe Excel-Datei.
---
## 7. Nachschlag für eine Folge-Iteration
Priorisiert nach erwartetem Erkenntnisgewinn je Aufwand:
### Rang 1 — Belegvalidierung vervollständigen
Die 39 noch nicht inhaltlich analysierten `Check*`-Methoden in `ReceiptBL.cs` (Zeilen 3703–3755) lesen. Jede von ihnen ist eine Geschäftsregel mit Pflichtfeld- oder Plausibilitätscharakter (Kostenstelle, Kostenträger, Umsatzsteuer-Identifikationsnummer, Leistungszeitraum, Bestellnummer, Projektnummer, Lizenznehmeranschrift, WEEE, Klassifizierung, Leasing/Service, Mandat, Prioritätsänderung, Zusatztext, E-Mail-Pflicht). **Erwarteter Zuwachs: 25–35 Anforderungen** im am dichtesten belegten Bereich.
### Rang 2 — Persistenzmechanik verifizieren
`AssetHeadDAO.SaveAssetVersion`, ein `SaveReceipt*Repository` und die zugehörigen `SynchronizeReceiptData`/`SynchronizeReceiptItemData` lesen. Damit werden SwRS-007 und SwRS-008 von dokumentations- auf codegestützt gehoben. **Hebt die Belastbarkeit der Persistenzarchitektur von „mittel bis niedrig" auf „hoch".**
### Rang 3 — Sicherheitsbefunde klären
Interception-Bridge lesen (`Centron.Host.AspNetCore.WcfBridge.Interception`), um H-01 zu entscheiden. Gezielt nach `DeveloperSecurity` bzw. `AllowSendingEmailToExternalAddresses` suchen, um H-04 zu entscheiden. `TelemetryUploadService.cs` und die 12 Telemetrieentitäten lesen, um H-05 zu entscheiden.
### Rang 4 — Nicht abgedeckte Fachbereiche erschließen
In dieser Reihenfolge: **SelfCare** (137 KB, sicherheitsrelevant wegen der anonymen Endpunkte), **Kalender/MyDay/TaskManager** (`ScheduleBL.cs`, 128 KB), **Finanzen** (`DunningBL.cs`, `BookKeepingExportBL.cs`), **EDI-Parser** (mindestens ein Distributorformat exemplarisch), **Provision** (`ReceiptProvisionBL.cs`), **Statistik** (`ContractEvaluationBL.cs`).
### Rang 5 — Datenmodell rekonstruieren
Die 764 Migrationsskripte maschinell zu einem Schemabild zusammenführen (Tabellen, Spalten, Typen, Indizes) und gegen die 983 NHibernate-Zuordnungen abgleichen. Damit entstünde erstmals ein belegtes, vollständiges Datenmodell — Grundlage jeder Datenmigration.
### Rang 6 — Traceability spiegeln und Lokalisierung auswerten
Alle Verweise beidseitig notieren. Die Ressourcendateien inhaltlich auswerten, um die Abdeckungslücke der englischen Fassung (rund 55 KB Differenz im WPF-Client) zu quantifizieren und deutschsprachige Literale im Backend systematisch zu erfassen.
---
## 8. Methodische Anmerkungen zu diesem Lauf
**Was gut funktioniert hat:**
- Die maschinelle Auszählung von Attributen, Endpunkten, Dateien und Konstanten lieferte belastbare, überprüfbare Kennzahlen ohne Interpretationsspielraum. Der Befund „221 Endpunkte ohne `[Authenticate]`" wäre durch Lesen nicht gefunden worden.
- Die Trennung von `Fakt` und `Aussage` erwies sich als wirksam: Bei SwRS-026 lässt sich dadurch klar sagen, dass der Ist-Zustand gesichert und nur die Soll-Aussage hypothetisch ist — was für die Validierung einen erheblichen Unterschied macht.
- Die Belegklassifikation zwang dazu, die umfangreiche `docs/`-Sammlung konsequent als `KONTEXT` zu behandeln. Dadurch wurden die dokumentationsgestützten Schwachstellen (Abschnitt 5.4) überhaupt sichtbar.
**Was die Ergebnisqualität begrenzt hat:**
- **Größenverhältnis.** 114 Anforderungen stehen 14 782 Quelldateien gegenüber. Die Auswahl der gelesenen Stellen ist die entscheidende Qualitätsgröße dieses Verfahrens — und sie beruhte auf Heuristiken (Dateigröße, Verzeichnisname, Rechtekonstanten als Wegweiser), nicht auf einer systematischen Abdeckungsstrategie.
- **Dokumentationssog.** Wo `docs/` eine fertige Architekturbeschreibung lieferte, wurde die Codeverifikation zurückgestellt. Das erklärt die Häufung dünner Belege genau in den architekturbeschreibenden Anforderungen.
- **Keine Ausführung.** Zustandsübergänge, Nebenläufigkeitsverhalten und tatsächliche Antwortzeiten sind nicht überprüfbar. Alle Performance- und Zuverlässigkeitsanforderungen beruhen auf Konfigurationswerten und Codestrukturen, nicht auf Messungen.
- **Change-Historie nur gestreift.** Von 52 135 Commits wurden 30 gelesen. Die Historie hätte Aufschluss über Änderungshäufigkeit, Fehlerschwerpunkte und faktische Nutzung der abgekündigten Bereiche geben können.
@@ -0,0 +1,160 @@
# Glossar
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
Alle in `StRS.md`, `SyRS.md` und `SwRS.md` verwendeten Domänen- und Systembegriffe. Jeder Eintrag nennt den Beleg im Quellcode. Technische Bezeichner (Klassen, Methoden, Spalten, Aufzählungswerte) bleiben in ihrer Originalsprache.
**Lesehilfe zur Zweisprachigkeit:** Die Codebasis führt viele Begriffe doppelt — deutsch in den historischen Datenbanktabellen, englisch in den modernen Entitäten und Sichten. Wo das zutrifft, sind beide Formen angegeben.
---
## A. Belegwesen
| Begriff | Definition | Beleg |
|---|---|---|
| **Beleg** (engl. *Receipt*) | Oberbegriff für alle Geschäftsdokumente mit Kopf- und Positionsdaten, Nummer, Datum, Version und Zustand. Umfasst sieben Kundenbeleg- und fünf Lieferantenbelegarten. | `Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` |
| **Kundenbeleg** | Beleg gegenüber einem Kunden: Angebot, Auftrag, Lieferschein, Rechnung, Abholschein, Gutschrift, Vertrag. | `CentronObjectKindNumeric.IsCustomerReceipt` |
| **Lieferantenbeleg** | Beleg gegenüber einem Lieferanten: Anfrage (*SupplierOffer*), Bestellung (*SupplierOrder*), Wareneingang (*SupplierDeliveryList*), WE-Kalkulation (*SupplierInvoice*), Lieferantengutschrift (*SupplierCreditVoucher*). | `CentronObjectKindNumeric.IsSupplierReceipt` |
| **Angebot** / *Offer* | Unverbindliches Preisangebot. Tabelle `AngKopf`/`AngPos`, Sicht `Offers`/`OfferItems`, Objektart 1. | `ReceiptOffer.cs`; `CentronObjectKindNumeric.OfferClass` |
| **Auftrag** / *Order* | Verbindliche Kundenbestellung. Tabelle `AufKopf`/`AufPos`, Sicht `Orders`/`OrderItems`, Objektart 2. | `ReceiptOrder.cs`; `OrderClass` |
| **Lieferschein** / *Delivery List* | Warenbegleitpapier. Tabelle `LiefKopf`/`LiefPos`, Sicht `DeliveryLists`, Objektart 3. | `ReceiptDeliveryList.cs`; `DeliveryListClass` |
| **Rechnung** / *Invoice* | Zahlungsforderung. Tabelle `RechKopf`/`RechPos`, Sicht `Invoices`, Objektart 4. | `ReceiptInvoice.cs`; `InvoiceClass` |
| **Abholschein** / *Pickup List* | Beleg über die Abholung durch den Kunden. Tabelle `AbholKopf`/`AbholPos`, Objektart 5. | `ReceiptPickupList.cs`; `PickupListClass` |
| **Gutschrift** / *Credit Voucher* | Rückerstattung oder Korrektur. Tabelle `GutKopf`/`GutPos`, Objektart 6. | `ReceiptCreditVoucher.cs`; `CreditVoucherClass` |
| **Vertrag** / *Contract* | Wiederkehrend abzurechnende Leistungsvereinbarung. Tabelle `VertragKopf`/`VertragPos`, Objektart 22. | `ReceiptContract.cs`; `ContractClass` |
| **Belegzustand** / *ReceiptState* | Genau einer von drei Werten: `Active = 1` („offen"), `Completed = 2` („abgeschlossen"), `Canceled = 3` („storniert"). | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| **Belegversion** | Fortlaufende Ganzzahl je Beleg. Zulässig sind beim Speichern nur die Erstversion (1), die aktuelle oder die unmittelbar folgende Version. Vorgängerstände liegen in `*KopfVersions`/`*PosVersions`. | `ReceiptBL.cs:3568-3578, 3117` |
| **Beleg-Muster** / *Receipt Template* | Wiederverwendbare Belegvorlage, erkennbar an einer **negativen** Belegnummer (`IsTemplate => Number < 0`) und dem festen Ersatzdatum 01.01.1970. | `ReceiptBase.cs:65`; `ReceiptBL.cs:3586-3593` |
| **Weiterverarbeitung** / *Forwarding* | Erzeugung eines Folgebelegs aus einem Ursprungsbeleg (z. B. Auftrag → Lieferschein). Positionsherkunft über `IReceiptItemWithOrigin.OriginKind`. | `ReceiptWebServiceBL.ForwardReceipt`; `ReceiptBL.GetReceiptForwardedInto` |
| **Nummernkreis** / *NumberGroup* | Je Belegart und Filiale geführter Zähler mit Startwert (`Current`), Intervall (`Interval`) und Wertebereich (`RangeFrom`/`RangeTo`). | `Centron.Data.Entities.Administration.Company.NumberGroup`; `NumberGroupBL.cs` |
| **Kontingent** / *Contingent* | In einem Vertrag vereinbartes Guthaben an Stunden oder Beträgen, das durch Leistungen verbraucht wird. Felder `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentBalance*`. | `ReceiptContract`; `ReceiptContractHelperBL.cs` |
| **Anzahlung** / *Down Payment* | Teilzahlung vor vollständiger Leistungserbringung; eigene Abrechnungslogik. | `Sales/Receipts/DownPayment/DownPaymentBL.cs` |
| **Kreditlimit** / *Credit Limit* | Kundenbezogene Obergrenze der offenen Belegsumme. Berechnung netto (`CreditLimitCalculationKind == 1`) oder brutto; Wert `2` oder `null` deaktiviert die Prüfung. | `ReceiptBL.CheckIfCustomerLimitIsReached` |
| **Mindestpreis** / *MinPrice* | Artikelbezogener Preis, der ohne das Recht `ALLOW_IGNORE_MINIMUM_PRICE` nicht unterschritten werden darf. | `ReceiptBL.CheckArticleMinPrices`; `Article.MinPrice` |
| **Aktionspreis** | Zeitlich befristeter Sonderpreis eines Distributors oder Herstellers. Tabelle `HerstellerArtikAktionspreis`. | `ActionPriceBL.cs`; `docs/reference/receipts/actionprice-system.md` |
| **Preisspiegel** | Vergleichende Übersicht der Einkaufspreise eines Artikels über bis zu sieben parallele Quellen (ITscope, Artikelimport, COP, NEOS, TradersGuide, EGIS, Aktionspreise). | `PriceMatrixViewModel`; `ArticleSearchBL.cs` |
---
## B. Abrechnung und Finanzen
| Begriff | Definition | Beleg |
|---|---|---|
| **Abrechnungsintervall** / *BillingIntervalKind* | `Daily = 0` („Tag(e)"), `Monthly = 1` („Monat(e)"), `Yearly = 2` („Jahr(e)"), `Quarterly = 3` („Quartal(e)"). Kombiniert mit `BillingIntervalDuration` (Anzahl). | `Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs` |
| **Abrechnungsweise** / *BillingKind* | `Billingadvance = 0` („vorschüssig") oder `Billingarrear = 1` („nachschüssig"). | `BillingKind.cs` |
| **Abrechnungsauslösung** / *ContractCalculationKind* | Flags-Aufzählung: `None = 0`, `Auto = 1` („automatische Abrechnung"), `Need = 2` („Abrechnung nach Bedarf"), `Manual = 4` („manuell Abrechnung"). | `ContractCalculationKind.cs` |
| **Kontingentgrenze** / *ContingentLimitKinds* | `Percent = 0` oder `Absolute = 1`. | `ContingentLimitKinds.cs` |
| **Vertragsabrechnung** / *AutomaticFactura* | Automatisierte Erzeugung von Rechnungen aus fälligen Verträgen. | `AutomaticFacturaBL.Contracts.cs`; `AutomaticFacturaWebServiceBL.cs` |
| **Mahnstufe** / *DunningLevel* | `None`, `Level1`, `Level2`, `Level3`. Ab einer belegartspezifischen Sperrstufe blockiert sie das Anlegen neuer Belege. | `Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs`; `ReceiptBL.cs:10205-10216` |
| **Offene Posten (OPOS)** | Noch nicht ausgeglichene Forderungen. Eigenes Modul und Objektart `OPOS = 7600101`. | `OposOverviewAppModuleController`; `CentronObjectKindNumeric.OPOS` |
| **Provisionsschema** | Regelwerk zur Ermittlung von Vertriebsprovisionen, kundenbezogen zugeordnet und zeitlich befristet. | `ReceiptProvisionSchema.cs`; `ReceiptProvisionBL.cs` |
| **ZUGFeRD** | Deutscher Standard für hybride elektronische Rechnungen (PDF/A mit eingebettetem XML). Im System unterstützte Fassungen: `ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2`, `_2_0`, `_2_2`, `_2_3_1`, `_3_0_1`. | `InvoiceZugferdBL.cs`; `ZugferdKind` |
| **XRechnung** | Verbindliches Rechnungsformat für öffentliche Auftraggeber in Deutschland; im System durch die Angabe einer Leitweg-ID ausgelöst. | `InvoiceZugferdBL.cs:153-156, 193` |
| **Leitweg-ID** | Kennung des öffentlichen Rechnungsempfängers. Ihr Vorhandensein schaltet das System von `ZugferdFileKind.Comfort` auf `.XInvoice` und die PDF-Konformitätsstufe von `EN16931` auf `XRechnung` um. | `InvoiceZugferdBL.GenerateZugferdFile` |
| **EN 16931** | Europäische Norm für die semantische Struktur elektronischer Rechnungen; im System als PDF-Konformitätsstufe verwendet. | `PdfZugferdConformanceLevel.EN16931` |
| **Kontenrahmen** / *AccountSystem* | Gliederung der Sachkonten für die Finanzbuchhaltung. | `AccountSystemsAppModuleController`; `BookKeepingAccountSystems` |
| **Mandat** / *SEPA-Mandat* | Einzugsermächtigung des Kunden. Objektart `SepaContract = 7600087`. | `ReceiptBL.CheckIfMandatIsNeeded`; `ReceiptContract.MandatI3D` |
| **ESR** | Schweizer Einzahlungsschein mit Referenznummer; eigene Feldbefüllung für Schweizer Belege. | `Sales/Receipts/Internal/ReceiptEsrBL.cs`; `IReceiptWithEsr` |
---
## C. Service und Ticketwesen
| Begriff | Definition | Beleg |
|---|---|---|
| **Helpdesk / Ticket** | Serviceanfrage eines Kunden. Objektart `HelpdeskClass = 10`, Tabelle `hlpdsk_requests`. | `HelpdeskBL.cs`; `CentronObjectKindNumeric.HelpdeskClass` |
| **Ticketzustand** | Anwenderpflegbares Stammdatum – **keine** feste Aufzählung im Code. Der Abschlusszustand wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` konfiguriert. | `HelpdeskBL.cs:433` |
| **Helpdeskzeit** / *HelpdeskTimer* | Erfasste Arbeitszeit an einem Ticket, verknüpfbar mit einer Belegposition. Objektart `HelpdeskTimerClass = 4000056`. | `HelpdeskTimerBL.cs`; `ReceiptItemTimerBL.cs` |
| **Mitarbeiterartikel** | Artikel, der einen Mitarbeiter für die Zeitabrechnung repräsentiert. | `EmployeeArticlesController.cs`; `CentronRights.md:50-53` |
| **Eskalation** | Regelbasierte Höherstufung eines Tickets bei Fristüberschreitung. Objektart `EscalationServer = 7600097`. | `Sales/Support/Escalation/EscalationBL.cs`; `EscalationsService.cs` |
| **Ticketvorlage** / *TicketPattern* | Vorlage zur automatisierten Ticketerstellung (C-FLOW). Objektart `TicketPattern = 7600093`. | `HelpdeskPatternBL.cs`; `TicketPatternsController.cs` |
| **C-FLOW** | Ticketprozess-/Vorlagensystem mit eigenem Rechteblock. | `UserRightsConst.Sales.Customer.Helpdesk.CFlow` |
| **Checkliste** | Strukturierte Aufgabenliste an einem Ticket. Objektart `Checklist = 7600082`. | `CheckListArea/`; `ChecklistsController.cs` |
| **Stammblatt** / *MasterDataList* | Geräte-/Anlagenverzeichnis eines Kunden, verknüpfbar mit Verträgen. Objektart `MasterDataListClass = 25`. | `ReceiptContractBL.AddMasteDateListsToContract` |
| **Web-Anfragezustand** / *RequestStateEnum* | Feste Aufzählung für Portalanfragen: `Requested = 0` („Angefragt"), `Veryfied = 1` („Verifiziert"), `Accepted = 2` („Angenommen"), `Denied = 3` („Abgelehnt"). | `RequestStateEnum.cs` |
---
## D. Lager und Artikel
| Begriff | Definition | Beleg |
|---|---|---|
| **Artikel** | Handelbare Ware oder Leistung. Objektart `Article = 9`. | `Warehousing/ArticleBL.cs` |
| **Warengruppe** / *MaterialGroup* | Klassifikation von Artikeln. Objektart `MaterialGroup = 70`, Nebenwarengruppe `SecondaryMaterialGroup = 136`. | `MaterialGroupBL.cs` |
| **Barcode / Seriennummer** | Eindeutige Kennung eines Einzelstücks. Artikel mit `NeedsBarcodes = true` verlangen je Positionsmenge einen erfassten Barcode. | `ReceiptBarcodeBL.cs`; `IReceiptItemWithBarcodes` |
| **Negative Lagerbuchung** | Buchung, die den Bestand unter null senkt **und** ihn dabei verringert. Eine Buchung, die einen bereits negativen Bestand anhebt, gilt ausdrücklich nicht als solche. | `ReceiptArticleBookingBL.cs:357-362` |
| **Kommissionierung** / *Commissioning* | Zusammenstellung der Ware für einen Auftrag, auch als Teilkommissionierung. | `PartialCommissionOrderBL.cs`; `OrderCommissionBL.cs` |
| **Inventur** / *Inventory* | Periodische Bestandsaufnahme mit eigenem Rechteblock (9 Rechte). | `InventoryBL.cs`; `UserRightsConst.Purchase.Inventory` |
| **RMA** | Rücksendevorgang (*Return Merchandise Authorization*). Objektarten `RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145`. | `CustomerArea/RmaBL.cs` |
---
## E. Berechtigung, Identität, Lizenz
| Begriff | Definition | Beleg |
|---|---|---|
| **Recht** / *AppRight* | Numerisch identifizierte Berechtigung, hierarchisch über `AppRight.Parent`. Tabelle `Sichrech`. Neue .NET-Rechte beginnen bei 20800000. | `UserRightsConst.cs`; `AppRightsBL.cs` |
| **Rechtegruppe** / *AppGroup* | Bündel von Rechten, optional filialbezogen (`BranchI3D`). Tabelle `Sichgrup`; Zuordnungen in `Sichtrus` (Gruppe↔Recht) und `Sichmemb` (Benutzer↔Gruppe). | `AppRightsBL.cs:651-664` |
| **Einschränkendes Recht** | Recht, dessen **Besitz** den Zugriff verengt statt ihn zu gewähren (z. B. `SHOW_HELPDESK_ONLY_OWN`). „nur eigene" hat Vorrang vor „nur eigene Filiale". | `HelpdeskBL.cs:269-291`; `CentronRights.md:9-17` |
| **Administratorgruppe** | Gruppe mit `I3D == 6` oder dem Namen „Administratoren". Nicht löschbar; ihre Rechtezuordnungen sind nur für 41 gelistete Rechte änderbar. | `AppRightsBL.cs:348-374, 714-759` |
| **Benutzer** / *AppUser* | Systemkonto eines Mitarbeiters, Tabelle `Sichbenu`. Trägt `AuthentificationKind`, `IsAccountDisabled`, `AccountDisabledFromDate`/`ToDate`, `LoginIP`. | `Centron.Data.Entities.Administration.AppUser` |
| **Web-Account** | Portalkonto eines Kundenansprechpartners mit **eigenem**, direkt kontobezogenem Rechtemodell (Tabelle `WebAccountsRights`). Kein Zugriff auf das interne Belegwesen. | `WebAccountBL.cs`; `WebAccountRightsConst`; `ReceiptBL.cs:10297-10302` |
| **Anwendungsart** / *ApplicationKind* | Eine der 44 anmeldefähigen Anwendungen mit Lizenz-GUID, Ticketablaufart, Lizenzzählweise sowie optional erforderlichem oder verbietendem Recht. | `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| **Sitzungsticket** / *Ticket* | Zeitlich begrenzte Sitzungskennung, gebildet aus einem 32-Zeichen-Zufallssalz und dem Gerätenamen. Gültigkeitsdauer je Anwendungsart: 5 Minuten (Monitoring), 30 Minuten (Standard), 1 440 Minuten (Tagesticket) oder aus Einstellung, mindestens 30 Minuten. | `TicketBL.cs:26-28, 136-170` |
| **Lizenz** | GUID, die den Besitz eines Produkts oder Einzelmerkmals darstellt; ergänzt um Anzahl, Gültigkeitsdatum und Gültigkeitsversion. 159 GUIDs definiert. | `LicenseGuids.cs`; `docs/reference/security/licensing-system.md` |
| **Lizenzzählweise** / *LicenseUsageKind* | `PerUserAndPerMachine` (Standard) oder `PerUser` (z. B. ServiceBoard). Bestimmt, wie belegte Lizenzen gezählt werden. | `ApplicationKind.cs`; `TicketBL.GetTicketCount` |
| **Zwei-Faktor-Authentifizierung** | Zweiter Anmeldefaktor über `RadiusServer` oder `EmailLink`. Gültigkeit je Benutzer in Tagen; `0` bedeutet: bei jeder Anmeldung. Gemerkt je Benutzer, Anwendung, Maschine und IP-Adresse. | `TwoFactorAuthBL.cs:33-193` |
---
## F. Organisation und Stammdaten
| Begriff | Definition | Beleg |
|---|---|---|
| **Mandant** / *Mandator* | Rechtliche Einheit im System. Objektart `Company = 53`. Nummernkreise werden stets auf dem Standardmandanten geführt. | `MandatorBL.cs`; `NumberGroupBL.cs:144-151` |
| **Filiale** / *Branch* | Organisatorische Untereinheit. Objektart `Branch = 124`. Belege tragen `BranchI3D`; ein Wert von `null` oder `0` bezeichnet die Standardfiliale. | `BranchBL.IsBranchEqual`; `ReceiptBL.cs:10258-10267` |
| **Filialherkunft** / *BranchOrigin* | Regel zur Ermittlung der Belegfiliale: `Creator` (Ersteller) oder `Adviser2` (Außendienstbetreuer). | `ReceiptBL.GetBranchForNewReceipt` |
| **Betreuer 1 / Adviser1** | Innendienstbetreuer eines Belegs, Feld `OfficeStaffI3D`. | `UserRightsConst…CHANGE_ADVISER1`; `ReceiptContract.OfficeStaffI3D` |
| **Betreuer 2 / Adviser2** | Außendienstbetreuer eines Belegs, Feld `SalesRepresentativeI3D`. | `UserRightsConst…CHANGE_ADVISER2` |
| **Kunde** / *Customer* | Objektart `Customer = 12` bzw. `CustomerClass = 5000012`; Legacy-Tabelle `Kunden`. | `CustomerBL.cs` |
| **Kreditor / Lieferant** | Objektart `Creditor = 20`; Legacy-Tabelle `Kreditor`. | `NumberGroupBL.cs:124-131` |
| **Ansprechpartner** / *ContactPerson* | Objektart `ContactPerson = 19`; Träger personenbezogener Daten und damit Gegenstand der DSGVO-Anonymisierung. | `ContactPersonBL.cs`; `DataSecurityBL.cs` |
| **Konto** / *Account* | Neueres, kunden- und lieferantenübergreifendes Adressmodell. Objektart `Account = 7600071`. Ersetzt bei aktivierter Einstellung `IsAccountManagementActive` den Adressstamm. | `AccountBL.cs`; `ModuleRegistration.cs:522-529` |
---
## G. Technische Systembegriffe
| Begriff | Definition | Beleg |
|---|---|---|
| **I3D** | Standardname des Primärschlüssels aller Tabellen (`int IDENTITY(1,1) NOT NULL`, gruppierter Primärschlüsselindex). Fremdschlüssel enden auf `I3D` mit dem Namen der referenzierten Tabelle als Präfix. | `docs/guides/database/database-conventions.md:12-35` |
| **Objektart** / *CentronObjectKindNumeric* | Stabile numerische Kennung eines Geschäftsobjekttyps; 205 Werte. Polymorphe Verweise werden als Paar `ObjectI3D` + `ObjectKind` (Legacy: `AnlageI3D` + `AnlageArt`) geführt. | `Centron.Interfaces/CentronObjectKindNumeric.cs` |
| **`Result<T>`** | Einheitliches Ergebnisobjekt aller Fachmethoden mit `Status` (`Success`/`Error`/`Warning`), `Message`, `MessageCode` und `Data`. Ersetzt Ausnahmen als Fehlerkanal. | `docs/getting-started/general-structure.md:30-35` |
| **ILogic / BLLogic / WSLogic** | Dreiteiliges Zugriffsmuster im Client: eine Schnittstelle mit zwei Implementierungen — direkter Datenbankzugriff (`BL*Logic`) und Web-Service-Aufruf (`WS*Logic`). | `docs/getting-started/general-structure.md:36-113` |
| **ClassContainer** | Singleton für die Auflösung der `ILogic`-Schnittstellen im Client. | `ClassContainer.Instance.WithInstance(...)` |
| **BLSession / DAOSession** | Sitzungsfassade für Fachlogik, Entitätszugriff, Repositories, parametrisiertes Roh-SQL, Zwischenspeicher und Transaktionsklammer. | `AppRightsBL.cs:105-110`; `ReceiptBL.cs:3544` |
| **SpecificLogic** | Belegartspezifische Strategieimplementierung von `IReceiptSpecificLogic`; 13 Ausprägungen. `ReceiptBL` delegiert jede belegartabhängige Entscheidung dorthin. | `IReceiptSpecificLogic.cs`; `Sales/Receipts/*/…SpecificLogic.cs` |
| **WebServiceBL** | Schicht zwischen Fachlogik und Schnittstelle; wandelt Entitäten in DTOs und zurück (AutoMapper-Profile unter `WebServices/ObjectMapperConfiguration/`). | `ReceiptWebServiceBL.cs` |
| **ScriptMethod** | Nummerierte, idempotente Datenbankskriptklasse (`ScriptMethod{Nummer}.cs`), beim Start des Web-Service ausgeführt. 764 Skripte vorhanden. | `Administration/Scripts/ScriptMethods/Scripts/`; `docs/reference/database/script-rules.md` |
| **ApplicationSettings** | Aktuelle Einstellungstabelle mit 492 Bezeichnern in `ApplicationSettingID`, je Eintrag mit Beschreibung. | `ApplicationSettingID.cs`; `ApplicationSettingDefinitions.cs` |
| **Stammdat** | Historische Einstellungstabelle mit 728 Bezeichnern in `AppSettingsConst`. Wird weiter gelesen und geschrieben, nimmt aber keine neuen Einstellungen mehr auf. | `AppSettingsConst.cs`; `docs/guides/development/settings-management.md:16-23` |
| **ChangeLog** | Feldgenauer Änderungsprotokolleintrag mit `ObjectI3D`, `ObjectKind`, `Property`, `OldValue`, `NewValue`, `Date`, `AppUser`. Erzeugt vom NHibernate-Ereignisempfänger für attributierte Entitäten. | `ChangeTrackingEventListener.cs` |
| **AnlageLog** | Historische, belegartübergreifende Protokolltabelle mit `AnlageI3D` + `AnlageArt`. | `docs/reference/receipts/receipts-backend-architecture.md:123-143` |
| **Versionstabelle** | Strukturgleiche Kopie einer Belegtabelle (`*KopfVersions`, `*PosVersions`), ergänzt um `OriginalI3D` und – bei Positionen – `KopfVersionsI3D`. | `docs/reference/receipts/receipts-backend-architecture.md:147-204` |
| **Temporäre Legacy-Entität** | Zwischenschicht des Schreibpfads: moderne Belegentitäten werden vor dem Speichern in Entitäten der deutschen Legacy-Tabellen übertragen. | `Centron.Entities/Entities/DbEntities/`; `SaveReceipt*Repository` |
| **ManagedBackgroundService** | Gemeinsame Basisklasse aller 35 Hintergrunddienste; regelt Anlaufverzögerung, Aktivierung, Fehlerbehandlung, Frequenzrücknahme und Laufzeitprotokollierung. | `Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs` |
| **Nexus** | Blazor-Server-Webportal, ausgeliefert unter der Marke „NEXOWARE ServiceBoard"; enthält ServiceBoard, WebCart, WebOffer und C-Sign. | `src/nexus/CentronNexus/`; `appsettings.json` (`Branding.Title`) |
| **WebCart** | Bestellportal für Endkunden des Anwenders; zeigt Artikel aus deren Sonderpreisen. | `src/nexus/CentronNexus/WebCart/`; `README.md:31-36` |
| **C-Sign** | Verfahren zur tokengebundenen Bereitstellung, Annahme und handschriftlichen Signatur von Dokumenten durch externe Empfänger. Objektarten `DocumentSigning = 7600133`, `DocumentSigningCustomerReceipts = 7600146`. | `DocumentSigningPage.razor`; `SignSharedDocument` |
| **RMM** | *Remote Monitoring and Management* – externes Überwachungssystem, aus dem nutzungsbasierte Abrechnungsmengen bezogen werden. Platzhalter `@@RMMArtikel@@` in der Rechnungsvorlage. | `AutomaticFacturaWebServiceBL.CheckRMMArticle`; `RiverConnectionBL` |
| **MSP** | *Managed Service Provider* – Betriebsmodell des Anwenderunternehmens; eigene Auswertungsmodule (`MspCollector`, `MSPComparer`, `MspDashboard`). | `UserRightsConst.MspCollector`; `ModuleRegistration.cs:651-661` |
| **EDI** | *Electronic Data Interchange* – elektronischer Belegaustausch mit Distributoren. Formate: OpenTrans 2.1, ALSO, ALSO CH, Herweck, Komsa, Alltron, ZUGFeRD. | `SupplierEdiBL.cs`; `Centron.Gateway/EDI_*` |
| **DSGVO-Löschung** | Anonymisierung statt physischer Löschung: personenbezogene Felder werden geleert, der Datensatz wird mit `IsDsgvoDeleted`, `DsgvoDeletedEmployeeI3D` und `DsgvoDeletedDate` gekennzeichnet; jeder entfernte Wert wird protokolliert. | `DataSecurityBL.cs:1195-1284` |
---
## H. Nicht verwendete, aber im Code vorhandene Begriffe
Diese Begriffe treten im Code auf, sind aber als `[Obsolete]` gekennzeichnet und wurden bewusst **nicht** in Anforderungen überführt (siehe `StRS.md`, Abschnitt 3, und `Hypothesen.md`, B-03):
**Riversuite**, **RiverSuiteCommonRights**, **Monitoring** (RMM-Vorgängersystem), **SupRemo** (Fernwartung), **DirectNow** (Echtzeitverbindung), **N13**, **Kassenbuch** / **Barrechnung** (`Sales.Cashbox`), **Dokumentationskategorien** (`Documentation.Categories`), **Telemarketing** (`RIGHT_SONDERAKTIONEN`).
@@ -0,0 +1,158 @@
# Hypothesen
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
Diese Datei sammelt alle Aussagen der Spezifikation, die sich **nicht eindeutig** aus den Artefakten ableiten lassen. Jede Hypothese nennt die offene Frage, die zur Bestätigung fehlende Information und den empfohlenen Klärungsweg. Sie sind der priorisierte Eingang in Schritt 7 der RRE-Methodenkette (Validierung durch Fachexperten).
**Anzahl:** 6 formal als `Status: HYPOTHESE` gekennzeichnete Anforderungen, ergänzt um 4 Beobachtungen ohne eigene Anforderung.
---
## A. Formal gekennzeichnete Hypothesen
### H-01 · SyRS-011 — Autorisierung der 221 nicht attributierten Legacy-Endpunkte
**Risikoklasse:** Sicherheit (höchste Priorität)
**Was belegt ist:** Von 2 599 Methoden der Legacy-REST-Schnittstelle tragen 2 374 das Attribut `[Authenticate]`. 221 Methoden tragen es nicht. Für einen Teil ist der anonyme Zugriff fachlich beabsichtigt und über einen Token bzw. eine GUID im Anfrageobjekt gesichert (`GetSharedDocumentByToken`, `SignSharedDocument`, `GetWebFormByGuid`, `GetWebRequestPageByGuid`, `GetWebLinkByGuid`) oder betrifft die Anmeldung und Auskunftsfunktionen (`Login`, `Logout`, `AuthenticateLogin`, `GetWebserviceVersion`, `GetSystemTime`, `GetDatabaseVersion`).
**Was nicht belegt ist:** Für schreibende Fachoperationen ohne erkennbaren Tokenschutz — nachgewiesen für `SaveCustomerSpecialArticle`, `DeleteCustomerSpecialArticle`, `SaveLogo`, `DeleteLogo`, `SaveOrUpdateContractExternalArticleImportHead`, `DeleteContractExternalArticleImportHead`, `SaveOrUpdateContractExternalArticleImportPositions`, `SaveAppointmentRequest`, `HandleAppointmentRequestReply`, `UpdateModuleFavorite`, `UpdateIgnoreRequiredFieldsSetting`, `UpdateWebAccountHelpdeskSettings`, `AssignTicketPatternToHelpdesk`, `CreateTicketPatternChildrenForTicket`, `CreateHelpdeskFromHelpdeskPattern`, `GetWebServiceMethodList` — ist kein alternativer Zugriffsschutz an der Methodensignatur erkennbar.
**Offene Frage:** Nimmt der WCF-/ASP.NET-Core-Bridge-Interceptor (`Centron.Host.AspNetCore.WcfBridge.Interception`) eine implizite Standardauthentifizierung für nicht attributierte Methoden vor — oder sind diese Endpunkte tatsächlich unauthentifiziert erreichbar?
**Fehlende Information:** Die Implementierung der Interception-Bridge liegt nicht als analysierbare Quelle im untersuchten Attributpfad; nur das Attribut selbst (`AuthenticateAttribute.cs`) war lesbar.
**Klärungsweg:** Laufzeitprüfung gegen eine Testinstanz (Aufruf von `DeleteLogo` ohne Ticket) **oder** Codeeinsicht in die Bridge durch die Entwicklung. Bei Bestätigung: sicherheitskritischer Befund mit sofortigem Handlungsbedarf, unabhängig von der Neuimplementierung.
**Belege:** `src/webservice/Centron.Host/Services/ICentronRestService.cs` (Deklarationen ohne `[Authenticate]`); `src/webservice/Centron.WebServices.Core/Interception/Interceptors/AuthenticateAttribute.cs`
---
### H-02 · SwRS-026 — Ablösbarkeit der ungesalzenen SHA-1-Kennwortspeicherung
**Risikoklasse:** Sicherheit (höchste Priorität)
**Was belegt ist — der Ist-Zustand, eindeutig durch `PRIMÄR`-Belege:** Kennwörter werden als **ungesalzener SHA-1-Wert** gespeichert und geprüft. `BasicAuthenticator.AuthenticateInternal` bildet `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` und sucht den Benutzer direkt über `where.Name == UserName && where.Password == decodedPassword` — das Kennwort ist damit Teil der Datenbankabfrage, ein Vergleich in konstanter Zeit findet nicht statt. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. `WebAccountBL.LoginWithWebAccount` verwendet dasselbe Verfahren für Portalkonten. Eine gesalzene Ableitungsfunktion (`CryptoUtils.CreateSalt(32)`, `CryptoUtils.CreatePasswordHash`) ist im System vorhanden, wird aber ausschließlich für Ticketkennungen verwendet.
**Was nicht belegt ist — die Soll-Aussage:** Ob eine Umstellung auf ein gesalzenes, rechenintensives Verfahren (z. B. PBKDF2, bcrypt, Argon2) im Zielsystem umsetzbar ist.
**Offene Frage:** Welche Randbedingungen bestehen für eine Migration der bestehenden Kennwörter — insbesondere: Greift die Delphi-Vorgängeranwendung „c-entron Delphi" weiterhin auf denselben Benutzerstamm (`Sichbenu`) zu und erwartet dort den SHA-1-Wert?
**Fehlende Information:** Der Zugriffspfad der Delphi-Anwendung auf die Kennwortspalte liegt außerhalb des Arbeitsverzeichnisses. `LicenseManager.TryFixCentronDelphiVersionNumber` belegt zwar, dass die Delphi-Anwendung dieselbe Lizenz und damit denselben Datenbestand nutzt, sagt aber nichts über den Anmeldepfad aus.
**Klärungsweg:** Aussage der Entwicklung zur Delphi-Kompatibilität und zur geplanten Ablösung. Prüfidee zum Nachweis des Ist-Zustands: Zwei Benutzer mit identischem Kennwort besitzen in der Datenbank denselben Kennwortwert.
**Belege:** `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50`; `src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:56-61`; `src/backend/Centron.BL/Administration/Logins/TicketBL.cs:166-170`
---
### H-03 · SyRS-041 — Transportverschlüsselung als Vorgabe
**Risikoklasse:** Sicherheit
**Was belegt ist:** Die ausgelieferten Beispiel- und Betriebskonfigurationen verwenden **unverschlüsseltes HTTP**: `WebServiceConfig.xml` enthält `<WebServiceAddress>http://localhost:1234/CentronService</WebServiceAddress>` mit leeren Zertifikatsknoten; die Portalkonfiguration enthält `Host.Url = http://localhost:8050/` mit leeren Feldern `LinuxCertificatePath`/`LinuxCertificatePassword`. HTTPS ist über `WebServiceCertificateFilePath` und `WebServiceCertificatePassword` nachrüstbar und in der Linux-Anleitung beschrieben.
**Was nicht belegt ist:** Dass HTTPS in produktiven Kundeninstallationen verbindlich ist. Es existiert kein Artefakt, das HTTPS erzwingt oder als Vorgabe setzt.
**Offene Frage:** Ist HTTPS in Kundeninstallationen verbindlich vorgeschrieben, oder wird der Web-Service typischerweise unverschlüsselt in einem als vertrauenswürdig angenommenen Netz betrieben?
**Fehlende Information:** Betriebsvorgabe außerhalb der Codebasis (Installationshandbuch, Vertragsanlage, Betriebskonzept).
**Klärungsweg:** Aussage der Betriebs-/Supportorganisation. Für das Zielsystem ist HTTPS als Pflicht zu setzen; die Frage betrifft nur die Bewertung des Ist-Zustands.
**Nachgelagerter Befund:** Das Zertifikatskennwort steht laut `docs/guides/services/web-service-on-linux.md:116-119` im Klartext in der Konfigurationsdatei — dies ist in der Projektdokumentation ausdrücklich als offener Punkt benannt („we should `encrypt` the certificate-password instead").
**Belege:** `docker/compose/WebServiceConfig.xml`; `src/nexus/CentronNexus.Host/appsettings.json`; `docs/guides/services/web-service-on-linux.md:35-58, 116-119`
---
### H-04 · SyRS-042 — Schutz vor E-Mail-Versand an Echtempfänger in Entwicklungsständen
**Risikoklasse:** Sicherheit / Datenschutz (mittel)
**Was belegt ist:** In der Docker-Entwicklungsumgebung existiert ein Mailcatcher-Dienst (`centron.azurecr.io/mailcatcher`, Ports 1025/1080) mit eigenem Dockerfile, der ausgehende Nachrichten abfängt. Die Projektdokumentation beschreibt zusätzlich eine Klasse `DeveloperSecurity`, die in DEBUG-Builds alle externen E-Mail-Adressen durch `test@nexoware.com` ersetzt; als intern gilt jede Adresse mit der Endung `nexoware.com`. In RELEASE-Builds greift der Schutz ausdrücklich nicht.
**Was nicht belegt ist:** Die Existenz und Wirkungsweise der Klasse `DeveloperSecurity` im Code. Eine Datei `DeveloperSecurity.cs` konnte im Arbeitsverzeichnis nicht gefunden werden.
**Offene Frage:** Existiert die beschriebene Adressersetzung noch, oder ist die Dokumentation veraltet und der Schutz besteht nur noch aus dem Mailcatcher der Entwicklungsumgebung?
**Fehlende Information:** `PRIMÄR`-Beleg für die Adressersetzung im Code.
**Klärungsweg:** Gezielte Suche nach `AllowSendingEmailToExternalAddresses` bzw. `test@nexoware.com` im Code in einer Folge-Iteration; falls erfolglos, Aussage der Entwicklung.
**Belege:** `docs/reference/security/developer-security.md:11-25` (KONTEXT); `docker/compose/compose.yaml`, `docker/c-entron-mailcatcher/Dockerfile` (PRIMÄR)
---
### H-05 · SwRS-037 — Inhalt und Rechtsgrundlage der Telemetrieübertragung
**Risikoklasse:** Datenschutz (mittel bis hoch, abhängig vom Inhalt)
**Was belegt ist:** Es existieren die Hintergrunddienste `TelemetryFlushService` (Intervall 1 Minute), `TelemetryUploadService` (12 KB) und `FlushAnalyticEventsService`, der Fachbereich `src/backend/Centron.BL/Telemetry/` sowie 12 Telemetrieentitäten unter `Centron.Entities/Entities/Telemetry` (u. a. `TelemetryLicenseKind`). Der Klassenkommentar in `LicenseGuids.cs` belegt die Kopplung an den Lizenzbestand: „Task: Update TelemetryLicenseKind.cs … enum, when new licenses were added."
**Was nicht belegt ist:** Welche Daten konkret erhoben und an wen übertragen werden, ob ein Personenbezug besteht und ob die Übertragung abschaltbar ist.
**Offene Frage:** Welchen Umfang hat die Telemetrie, welche Rechtsgrundlage liegt zugrunde, und ist das Anwenderunternehmen darüber informiert?
**Fehlende Information:** `TelemetryUploadService.cs` und die 12 Telemetrieentitäten wurden in dieser Iteration nicht im Detail ausgelesen (Priorisierungsentscheidung, siehe `Analysebericht.md`).
**Klärungsweg:** Nachschlag in einer Folge-Iteration mit vollständiger Analyse des Telemetriedatenmodells; anschließend Abgleich mit der Datenschutzerklärung gegenüber dem Anwenderunternehmen.
**Belege:** `src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryUploadService.cs`; `src/backend/Centron.BL/Telemetry/`; `src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs:7`
---
### H-06 · SwRS-010 — Bewertung der reflexionsbasierten Auflösung generischer Belegoperationen
**Risikoklasse:** Wartbarkeit / Performance (niedrig)
**Was belegt ist:** `ReceiptBL.SaveReceipt(IReceiptBase, …)` und `ReceiptBL.CreateNewVersion(CentronObjectKindNumeric, …)` ermitteln die generische Überladung zur Laufzeit über Reflexion (`GetMethods().First(f => f.IsGenericMethod).MakeGenericMethod(...)`) und rufen sie per `Invoke` auf. Typfehler werden dadurch erst zur Laufzeit sichtbar.
**Was nicht belegt ist:** Ob die Reflexion eine bewusste Entwurfsentscheidung (z. B. wegen der nicht-generischen Signatur der Legacy-Schnittstelle) oder eine ablösbare Altlast ist.
**Offene Frage:** Kann die Auflösung im Zielsystem statisch typisiert erfolgen, oder erzwingt die aufrufende Schnittstelle die dynamische Auflösung?
**Fehlende Information:** Kommentar oder Entwurfsnotiz an der Codestelle; beide Methoden sind unkommentiert.
**Klärungsweg:** Aussage der Entwicklung. Die Frage betrifft die Zielarchitektur, nicht das Ist-Verhalten.
**Belege:** `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3517-3521, 3063-3067`
---
## B. Beobachtungen ohne eigene Anforderung
Diese Punkte sind belegt, waren aber im Rahmen dieser Iteration nicht ausreichend analysierbar, um daraus eine testbare Anforderung zu formulieren. Sie sind für die Validierung dokumentiert.
### B-01 · Kopiermechanik der Belegversionierung nicht im Detail gelesen
Die Aussage, dass Versionstabellen strukturgleiche Kopien sind und über eine dynamisch erzeugte Feldliste (`DoGetFieldList()`, `AssetHeadDAO.SaveAssetVersion`) befüllt werden, stützt sich auf die Projektdokumentation (`docs/reference/receipts/receipts-backend-architecture.md:147-204`) und den Aufrufpunkt im Speicherpfad (`ReceiptBL.cs:3629`). Die Implementierung in `AssetHeadDAO` wurde nicht gelesen. **Auswirkung:** SwRS-008 trägt daher den Zusatz `Workaround` und stützt sich überwiegend auf `KONTEXT`-Belege. **Nachschlag:** `Centron.DAO`-Analyse von `AssetHeadDAO.SaveAssetVersion`.
### B-02 · Konsistenz zwischen `AppRight.Text` und `UserRightsConst`
`UserRightsConst` definiert die Recht-IDs als Konstanten; die anwendersichtbaren Rechtebezeichnungen liegen dagegen in der Datenbanktabelle `Sichrech` im Feld `Text`. Ein Abgleich zwischen beiden ist im Code nicht erkennbar. **Offene Frage:** Wie wird sichergestellt, dass eine im Code eingeführte Recht-ID auch in der Datenbank mit einer Bezeichnung existiert? Die Datei `DefaultRightsStructure.txt` deckt nur die Standardgruppen ab, nicht die Rechtestammdaten selbst. **Auswirkung:** keine Anforderung formuliert; Frage betrifft die Datenpflege.
### B-03 · Abgekündigte Funktionsbereiche
Erhebliche Teile von `UserRightsConst` sind mit `[Obsolete]` gekennzeichnet: die vollständigen Blöcke `Monitoring` (17 Rechte), `SupRemo` (6), `DirectNow` (2), `Riversuite` (8), `RiverSuiteCommonRights` (3), `N13` (2), `Sales.Cashbox` (7) sowie zahlreiche Einzelrechte. Ebenso ist der Bereich `Documentation.Categories` vollständig abgekündigt. **Offene Frage:** Sind die zugehörigen Funktionen bei Kunden noch im Einsatz, oder können sie in der Neuimplementierung ersatzlos entfallen? **Auswirkung:** Diese Bereiche wurden bewusst aus dem Anforderungsumfang ausgeschlossen (siehe `StRS.md`, Abschnitt 3 „Abgrenzung"). Eine Fehleinschätzung würde Funktionslücken im Zielsystem verursachen.
### B-04 · Skriptnummernvergabe außerhalb der Versionsverwaltung
Die Nummernvergabe für Datenbankskripte (`ScriptMethod{Nummer}.cs`) erfolgt laut `docs/reference/database/script-rules.md:12-15` über eine externe, in Teams abgelegte Excel-Datei. Damit ist die Eindeutigkeit der Nummern nicht durch das Versionsverwaltungssystem gesichert. **Offene Frage:** Ist es in der Vergangenheit zu Nummernkollisionen gekommen, und wie wurden sie aufgelöst? **Auswirkung:** In SwRS-033 als `Workaround` vermerkt.
---
## C. Priorisierung für die Validierung
| Rang | Hypothese | Begründung |
|---|---|---|
| 1 | **H-01** (221 offene Endpunkte) | Unmittelbares Sicherheitsrisiko im Produktivsystem, unabhängig von der Neuimplementierung |
| 2 | **H-02** (SHA-1 ohne Salt) | Ist-Zustand gesichert; die Klärung betrifft nur die Migrationsstrategie, der Handlungsbedarf steht fest |
| 3 | **H-05** (Telemetrieinhalt) | Möglicher Personenbezug ohne bekannte Rechtsgrundlage |
| 4 | **B-03** (abgekündigte Bereiche) | Fehleinschätzung führt zu Funktionslücken im Zielsystem |
| 5 | **H-03** (HTTPS) | Betriebsfrage; im Zielsystem ohnehin als Pflicht zu setzen |
| 6 | **H-04** (E-Mail-Schutz) | Betrifft nur Entwicklungsstände |
| 7 | **B-01** (Versionierungsmechanik) | Detailfrage der Persistenz; durch Nachschlag im Code lösbar |
| 8 | **H-06** (Reflexion) | Reine Zielarchitekturfrage ohne Ist-Risiko |
| 9 | **B-02** (Rechtebezeichnungen) | Datenpflegefrage ohne funktionale Auswirkung |
| 10 | **B-04** (Skriptnummern) | Prozessfrage der Entwicklung |
@@ -0,0 +1,592 @@
# StRS – Stakeholder Requirements Specification
**System:** NEXOWARE c-entron ERP (c-entron.NET, c-entron Web-Service, c-entron Nexus / ServiceBoard, Outlook Add-In)
**Verfahren:** Reverse Requirements Engineering (statische Artefaktanalyse), ISO/IEC/IEEE 29148:2018
**Analysebasis:** Git-Arbeitskopie `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48` (Stand 2026-08-25)
**Erstellt:** 2026-08-25 · **Iteration:** V1 Baseline (Prompt-only), Lauf 01
---
## 0. Lesehinweise
- **Fakt** enthält ausschließlich die im Artefakt beobachtete technische Tatsache.
- **Aussage** enthält die daraus abgeleitete fachliche Soll-Aussage (Interpretation).
- Belegklassen: `PRIMÄR` = durchgesetzte Regel in Code oder DB-Constraint · `SEKUNDÄR` = UI-Label, Fehlermeldung, Mappingtabelle, Konfigurationsschalter, Reportlayout · `KONTEXT` = Kommentar, Commit-Message, Projektdokumentation, Ticketreferenz.
- Pfade sind relativ zur Repository-Wurzel.
- Alle Domänenbegriffe sind in `Glossar.md` definiert.
- Alle mit `[HYPOTHESE]` markierten Aussagen sind zusätzlich in `Hypothesen.md` gesammelt.
**Wichtige Abgrenzung zu Projektdokumentation:** Das Repository enthält unter `docs/` eine umfangreiche Entwicklerdokumentation. Diese wird durchgängig als `KONTEXT` klassifiziert, weil sie nicht ausführbar ist und vom Code abweichen kann. Wo eine Anforderung auf Sicherheits-, Abrechnungs- oder Berechtigungslogik zielt, wurde zusätzlich ein `PRIMÄR`-Beleg im Code gesucht; ist keiner vorhanden, ist die Anforderung als `[HYPOTHESE]` gekennzeichnet.
---
## 1. Systemzweck und Stakeholder
### 1.1 Identifizierte Stakeholder-Rollen
| Rolle | Herleitung aus Artefakten |
|---|---|
| **Innendienst / Sachbearbeiter Vertrieb** | Belegrechte `UserRightsConst.Sales.Customer.CustomerCommon.Offer/Order/Invoice/...`, Feld `OfficeStaffI3D` ("Adviser1") an Belegen |
| **Außendienst / Vertriebsmitarbeiter** | Feld `SalesRepresentativeI3D` ("Adviser2"), `UserRightsConst.Sales.Provision.*` |
| **Servicetechniker / Ticketbearbeiter** | `UserRightsConst.Sales.Customer.Helpdesk.*`, `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL` |
| **Lagerist / Logistik** | `UserRightsConst.Logistic.*`, `UserRightsConst.Purchase.StockList.*`, `OrderCommissionBL`, `InventoryBL` |
| **Einkäufer** | `UserRightsConst.Purchase.Supplier.*`, `SupplierEdiBL` |
| **Buchhaltung / Controlling** | `UserRightsConst.Controlling.Finances.*`, `BookKeepingExportBL`, `DunningBL` |
| **Systemadministrator (Anwenderseite)** | `UserRightsConst.Administration.*`, Modul `RightsManagamentAppModuleController`, `SettingsAppModuleController` |
| **Datenschutzbeauftragter** | `UserRightsConst.DsgvoModule.*`, `DataSecurityBL` |
| **Endkunde des Anwenders (Web-Account)** | `WebAccount`-Entität, `WebAccountRightsConst`, `src/nexus/CentronNexus/ServiceBoard`, `WebCart` |
| **Lieferant / Distributor** | EDI-Konfigurationen `SupplierEdiConfigurations`, `src/apis/*` |
| **Hersteller/Betreiber (NEXOWARE Systems GmbH)** | `Directory.Build.props` (`<Company>`), Lizenzserver-Anbindung `LicenseManager`, `LicenseGuids.CentronInternal` |
---
## 2. Stakeholder-Anforderungen
```
ID: StRS-001
Titel: Integriertes ERP-Kernsystem für IT-Systemhäuser
Ebene: StRS
Typ: funktional
Akteur: Anwenderunternehmen (IT-Systemhaus / MSP)
Vorbedingung: Das Unternehmen betreibt Vertrieb, Einkauf, Lager, Service und Abrechnung in einem gemeinsamen Datenbestand.
Fakt: Die Solution `Centron.sln` bündelt 44 Projekte; die Modulregistrierung `ModuleRegistration.cs` gliedert die Anwendung in 15 Modulgruppen (Abrechnung, Administration, Adressen/CRM, Automatisierung, Buchhaltung/Finanzen, Controlling/Analytics, Einkauf, Helpdesk, Hilfe, Logistik, MyCentron, Passwort Manager, Produktion, Stammdaten, Verträge) mit insgesamt 84 registrierten Modul-Controllern.
Aussage: Das System soll die Geschäftsprozesse Vertrieb, Einkauf, Lager/Logistik, Service/Helpdesk, Vertrags- und Abrechnungsmanagement, Buchhaltungsanbindung sowie Controlling in einem integrierten Datenmodell abbilden.
Ergebnis: Ein Anwender kann sämtliche genannten Prozesse ohne Systemwechsel und ohne Datenexport zwischen Fachbereichen ausführen.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:418-905 (`#region c-entron Module: …`, 84× `ModuleRegistrationItem.For<…>`) - Begründung: Die Modulliste ist die im Code durchgesetzte Definition des Funktionsumfangs der Client-Anwendung; sie wird zur Laufzeit ausgewertet und bestimmt, welche Module überhaupt existieren.
- [PRIMÄR] src/backend/Centron.BL/ (Domänenordner: Sales, Warehousing, Administration, CustomerArea, Accounts, EDI, Statistics, Finances, …) - Begründung: Die Ordnerstruktur der Geschäftslogik spiegelt dieselben Domänen wider und belegt, dass die Fachlogik gemeinsam in einer Assembly und gegen eine Datenbank arbeitet.
- [KONTEXT] docs/getting-started/ai-codebase-navigation.md:14-29 (Top-level layout) - Begründung: Bestätigt die Zuordnung der Projektbereiche zu fachlichen Rollen.
Prüfidee: Für jede der 15 Modulgruppen ist mindestens ein registrierter Modul-Controller nachweisbar und über die Oberfläche erreichbar, sofern Recht und Lizenz vorliegen.
Tracelinks: SyRS-015, SyRS-031, SyRS-032, SyRS-033; SwRS-001, SwRS-036, SwRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-002
Titel: Rollenbasierte Zugriffssteuerung über Rechtegruppen
Ebene: StRS
Typ: Sicherheit
Akteur: Systemadministrator (Anwenderseite)
Vorbedingung: Es existieren Benutzerkonten und Rechtegruppen im System.
Fakt: Rechte werden nicht direkt an Benutzer vergeben: `AppRightsBL.GetAllAppRightsFromUser` ermittelt Rechte über `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D`. `Sichmemb` verknüpft Benutzer mit Gruppen, `Sichtrus` Gruppen mit Rechten. `UserRightsConst` definiert über 900 numerische Recht-IDs in einer hierarchischen Klassenstruktur.
Aussage: Das System soll Berechtigungen ausschließlich über die Zuordnung Benutzer → Rechtegruppe → Recht vergeben, sodass Berechtigungen zentral über Gruppen administrierbar sind.
Ergebnis: Ein Benutzer besitzt genau die Vereinigungsmenge der Rechte aller Gruppen, denen er angehört.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:651-664 (`GetAllAppRightsFromUser`, SQL über `Sichtrus`/`Sichmemb`) - Begründung: Dies ist die einzige Auflösungsstelle für Benutzerrechte im Backend; sie zeigt das Datenmodell und die durchgesetzte Auflösungsregel.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:63-87 (`GetRightsFromCurrentUser`: Iteration über `user.Groups` → `group.Rights`) - Begründung: Bestätigt dieselbe Semantik auf Entitätsebene (Vereinigungsmenge über Gruppen).
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (gesamt) - Begründung: Zentrale, hierarchisch gegliederte Definition aller Rechtekonstanten.
- [KONTEXT] docs/guides/development/check-userrights.md:3 ("Rights and groups can be managed in the `Rechteverwaltung` module.") - Begründung: Bestätigt die administrative Sicht auf dasselbe Modell.
Prüfidee: Wird einem Benutzer eine Gruppe entzogen, sind alle ausschließlich über diese Gruppe vermittelten Rechte unmittelbar nach Cache-Ablauf nicht mehr wirksam.
Tracelinks: SyRS-009, SyRS-012, SyRS-013, SyRS-014, SyRS-047; SwRS-002, SwRS-003, SwRS-040
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-003
Titel: Mandanten- und Filialfähigkeit mit Sichtbarkeitseinschränkung
Ebene: StRS
Typ: funktional
Akteur: Anwenderunternehmen mit mehreren Standorten
Vorbedingung: Im System sind mehrere Filialen (`Branch`) und mindestens ein Mandant (`Mandator`) angelegt.
Fakt: Belege tragen `BranchI3D` und `BranchOrigin`; Nummernkreise werden je Filiale geführt (`NumberGroup.BranchI3D`, `NumberGroupBL.CreateNumberGroups(mandantI3D, branchI3D)`). Für nahezu jede Belegart existieren einschränkende Rechte `*_ONLY_OWN_BRANCH` (z. B. `SHOW_OFFERS_ONLY_OWN_BRANCH = 20400150`, `EDIT_INVOICE_ONLY_OWN_BRANCH = 20800031`, `CREATE_NEW_ORDER_ONLY_OWN_BRANCH = 20400212`), die in `ReceiptBL.CanUserCreateReceiptsInBranch` und `ReceiptBL.CanUserEditReceipt` gegen `appUser.Employee.BranchI3D` geprüft werden.
Aussage: Das System soll Daten filialbezogen führen und die Sichtbarkeit sowie Bearbeitbarkeit von Belegen, Tickets, Statistiken und Rechtegruppen auf die Filiale des Benutzers einschränken können.
Ergebnis: Ein Benutzer mit einschränkendem Filialrecht sieht und bearbeitet ausschließlich Datensätze der eigenen Filiale; Datensätze der Standardfiliale gelten dabei als eigene Filiale, wenn auch der Benutzer der Standardfiliale zugeordnet ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10251-10270 (`CanUserCreateReceiptsInBranch`) - Begründung: Setzt die Filialbeschränkung beim Neuanlegen durch, inkl. der Sonderregel für die Standardfiliale (`userBranchIsDefaultBranch && receiptBranchIsDefaultBranch`).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10272-10295 (`CanUserEditReceipt`, `BranchBL.IsBranchEqual`) - Begründung: Setzt dieselbe Beschränkung beim Bearbeiten durch.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48 und 355-357 (`MANAGE_RIGHTS_ONLY_OWN_BRANCH`) - Begründung: Zeigt, dass die Filialbeschränkung auch die Rechteverwaltung selbst umfasst.
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:136-152 (`RefreshAllNumberGroups`, Nummernkreis je Filiale) - Begründung: Belegt filialbezogene Nummernkreise.
- [SEKUNDÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs (`Branch`-Lizenz) - Begründung: Filialfähigkeit ist ein separat lizenziertes Merkmal.
Prüfidee: Ein Benutzer der Filiale A mit Recht `SHOW_INVOICES_ONLY_OWN_BRANCH` erhält beim Öffnen einer Rechnung der Filiale B eine Rechtefehlermeldung.
Tracelinks: SyRS-013, SyRS-018; SwRS-002, SwRS-004
Konsolidierung: Kandidat: Die Filialprüfung ist je Belegart über eigene Recht-IDs und über `IReceiptSpecificLogic.HasRightToEditReceiptOnlyOwnBranch` dupliziert; im Zielsystem als ein generischer Scope-Filter zusammenführbar (vgl. SyRS-006).
Status: belegt
```
```
ID: StRS-004
Titel: Lizenzbasierte Freischaltung von Anwendungen und Einzelfunktionen
Ebene: StRS
Typ: funktional
Akteur: Hersteller (NEXOWARE Systems GmbH) / Anwenderunternehmen
Vorbedingung: Der Web-Service hat eine gültige Lizenzdatei vom Lizenzserver bezogen oder aus dem lokalen Cache geladen.
Fakt: `LicenseGuids.cs` definiert 159 Lizenz-GUIDs. `ApplicationKind.cs` definiert 44 anmeldefähige Anwendungen, jeweils mit `LicenseGuid`, optionalen `AdditionalLicenseGuids`, `ExpirationKind`, `LicenseUsageKind` sowie optional `RequiredRight`/`DisallowingRight`. `LicenseManager.CheckLicense` prüft Version (`CheckLicenseVersion`) und Anzahl gleichzeitig genutzter Lizenzen (`GetLicenseCount` vs. `TicketBL.GetTicketCount`). In `ModuleRegistration.cs` ist jedes Modul mit einer Kombination aus Rechteprüfung UND Lizenzprüfung registriert.
Aussage: Das System soll die Verfügbarkeit von Anwendungen und einzelnen Funktionsmodulen an den Besitz einer Lizenz, deren Gültigkeitsversion und deren Nutzeranzahl koppeln.
Ergebnis: Ohne passende Lizenz ist ein Modul in der Oberfläche nicht sichtbar; ohne gültige Anwendungslizenz schlägt die Anmeldung mit einer lizenzbezogenen Fehlermeldung fehl.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:258-302 (`CheckLicense`, `DefaultMessageCodes.LicenseMaximumReached`) - Begründung: Durchgesetzte Prüfung von Lizenzbesitz, Version und Nutzungsanzahl vor Ticketerzeugung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:131-139 (`LicenseManager.CheckLicense(...)` im Anmeldepfad) - Begründung: Zeigt, dass die Anmeldung ohne erfolgreiche Lizenzprüfung abgebrochen wird.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:421-448 u. a. (`ModuleRegistrationItem.For<T>(rechteLambda, lizenzLambda)`) - Begründung: Modulsichtbarkeit ist im Code hart an `LicenseManager.Instance.HasLicense(...)` gebunden.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs:10-53 - Begründung: Definiert die anmeldefähigen Anwendungen und ihre Lizenzkopplung.
- [KONTEXT] docs/reference/security/licensing-system.md:3-31 - Begründung: Beschreibt Lizenzmodell (GUID, count, valid until date, valid until version) fachlich.
Prüfidee: Entzieht man die Lizenz `LicenseGuids.PasswordManager`, ist das Modul „Passwort Manager" nach Neustart des Clients nicht mehr in der Modulliste enthalten, obwohl die Rechte unverändert sind.
Tracelinks: SyRS-006, SyRS-007, SyRS-008, SyRS-015; SwRS-005
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Durchgängige Belegkette vom Angebot bis zur Rechnung
Ebene: StRS
Typ: funktional
Akteur: Innendienst / Sachbearbeiter Vertrieb
Vorbedingung: Ein Kunde ist im Adressstamm angelegt und nicht gesperrt.
Fakt: `CentronObjectKindNumericExtensions.IsCustomerReceipt` definiert genau sieben Kundenbelegarten: Angebot (1), Auftrag (2), Lieferschein (3), Rechnung (4), Abholschein (5), Gutschrift (6), Vertrag (22). Alle erben von `ReceiptBase` mit gemeinsamen Feldern Number/Date/Version/State. `ReceiptWebServiceBL.ForwardReceipt(...)` erzeugt Folgebelege aus Ursprungsbelegen; `IReceiptItemWithOrigin` (Felder `OriginKind`, Herkunftsverweis) hält die Herkunft je Position fest; `ReceiptBL.GetReceiptForwardedInto(...)` ermittelt, in welche Folgebelege ein Beleg weiterverarbeitet wurde.
Aussage: Das System soll die Belegarten Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift und Vertrag als Kundenbelege führen und die Weiterverarbeitung eines Belegs in einen Folgebeleg positionsgenau nachvollziehbar machen.
Ergebnis: Zu jeder Belegposition ist die Ursprungsposition und zu jedem Beleg die Menge der daraus erzeugten Folgebelege ermittelbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:273-287 (`IsCustomerReceipt`) - Begründung: Abschließende, im Code durchgesetzte Aufzählung der Kundenbelegarten.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72 - Begründung: Gemeinsame Belegkopf-Struktur aller Belegarten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3111-3114 (`GetReceiptForwardedInto(...)` blockiert neue Versionen bei bereits weiterverarbeiteten Belegen) - Begründung: Beweist, dass Weiterverarbeitungsbeziehungen persistiert und geschäftsregelrelevant sind.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1815-1841 (`receiptBL.ForwardReceipt(CentronObjectKindNumeric.InvoiceClass, …, originReceipts: [ReceiptKind = ContractClass])`) - Begründung: Konkreter Nachweis der Belegkettenbildung Vertrag → Rechnung.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:37-45 (Tabelle Belegart/Entität/Tabelle/View) - Begründung: Ordnet den Belegarten die persistierenden Strukturen zu.
Prüfidee: Wird aus einem Auftrag ein Lieferschein erzeugt, liefert `GetReceiptForwardedInto` für den Auftrag den Lieferschein; die Lieferscheinposition trägt `OriginKind = OrderClass`.
Tracelinks: SyRS-016, SyRS-017, SyRS-018, SyRS-019, SyRS-020, SyRS-022, SyRS-023; SwRS-006, SwRS-007, SwRS-009, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-006
Titel: Vertragsverwaltung mit wiederkehrender, automatisierter Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung / Vertragsverwaltung
Vorbedingung: Ein Vertrag (Belegart `ContractClass`) ist angelegt und aktiv.
Fakt: `BillingIntervalKinds` definiert `Daily=0`, `Monthly=1`, `Yearly=2`, `Quarterly=3`; `BillingKinds` definiert `Billingadvance=0` („vorschüssig") und `Billingarrear=1` („nachschüssig"); `ContractCalculationKind` ist ein `[Flags]`-Enum mit `None=0`, `Auto=1` („automatische Abrechnung"), `Need=2` („Abrechnung nach Bedarf"), `Manual=4` („manuell Abrechnung"). `AutomaticFacturaWebServiceBL.CreateInvoiceToContractComplete` erzeugt aus Verträgen Rechnungen. Der Hintergrunddienst `ContractEndeService` und `ContractCloseService` laufen im Web-Service-Host.
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall (Tag, Monat, Quartal, Jahr), Intervalldauer sowie vor- oder nachschüssiger Abrechnungsweise führen und daraus automatisch, bedarfsgesteuert oder manuell Rechnungen erzeugen.
Ergebnis: Für einen fälligen Vertrag entsteht eine Rechnung, deren Positionen aus den vertragsrelevanten Vertragspositionen abgeleitet sind und deren Abrechnungszeitraum dem konfigurierten Intervall entspricht.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs - Begründung: Abschließende Aufzählung der zulässigen Abrechnungsintervalle mit deutschsprachigen Anzeigetexten.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingKind.cs - Begründung: Definiert vor-/nachschüssige Abrechnung als Geschäftsregel.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/ContractCalculationKind.cs - Begründung: Definiert die Auslösearten der Abrechnung.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1699-1841 (`CreateInvoiceToContractComplete`) - Begründung: Implementiert die Rechnungserzeugung aus Verträgen einschließlich Zählerdaten und Staffelpreisen.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ContractEndeService.cs, ContractCloseService.cs - Begründung: Belegt automatisierte, zeitgesteuerte Vertragsverarbeitung im Serverbetrieb.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:42-95 - Begründung: Beschreibt die Vertragsattribute fachlich (Kontingent, Prolongation, Monitoring).
Prüfidee: Ein Vertrag mit `BillingIntervalKind = Monthly`, `BillingIntervalDuration = 3`, `BillingKind = Billingadvance` erzeugt zu Quartalsbeginn genau eine Rechnung über den kommenden Dreimonatszeitraum.
Tracelinks: SyRS-023, SyRS-029; SwRS-009, SwRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Ticket-/Helpdesk-Management mit abrechenbarer Zeiterfassung
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker / Ticketbearbeiter
Vorbedingung: Der Benutzer besitzt das Recht `SHOW_HELPDESK`; ein Kunde ist zugeordnet.
Fakt: Der Objekttyp `HelpdeskClass = 10` und `HelpdeskTimerClass = 4000056` sind eigenständige Objektarten. `HelpdeskBL`, `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL`, `HelpdeskTimerArticleBookingBL` und `ReceiptItemTimerBL` (104 KB) verbinden Ticketzeiten mit Belegpositionen. `UserRightsConst.Sales.Customer.Helpdesk` enthält 26 Rechte, u. a. `EDIT_TIME`, `OWN_TIME_EDIT`, `MOVE_HELPDESK_TIMER`, `DELETE_HELPDESK_TIMER`, `SHOW_ALL_EMPLOYEE_TIMES`. Das Modul `TimerBillingAppModuleController` („Vereinfachte Ticketabrechnung") ist an das Recht `TIMER_BILLING_MODULE` und die Lizenz `SimplifiedTicketBilling` gebunden.
Aussage: Das System soll Serviceanfragen als Tickets führen, geleistete Zeiten je Ticket und Mitarbeiter erfassen und diese Zeiten als Positionen in Kundenbelege überführen können.
Ergebnis: Eine erfasste Ticketzeit ist eindeutig einem Ticket, einem Mitarbeiterartikel und – nach Abrechnung – einer Belegposition zugeordnet und kann danach nicht mehr frei verschoben oder gelöscht werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemTimerBL.cs - Begründung: Implementiert die Verbindung Ticketzeit ↔ Belegposition (`FillReceiptWithTimerI3Ds`, aufgerufen in `ReceiptBL`).
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3691 (`UpdateArticlePositionsHelpdeskTimerI3Ds(receipt)`) - Begründung: Beim Belegspeichern werden Ticketzeit-Referenzen an Positionen fortgeschrieben.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1952-2015 (Helpdesk-Rechteblock) - Begründung: Definiert die durchgesetzten Rechte rund um Ticketzeiten.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:441-443 (Modul „Vereinfachte Ticketabrechnung") - Begründung: Belegt die Abrechnung von Ticketzeiten als eigenständige, lizenzierte Fachfunktion.
- [KONTEXT] CentronRights.md:59-66 („Helpdeskzeiten verschieben … aber nur, wenn das Ticket nicht Teil eines Belegs ist") - Begründung: Fachliche Formulierung der Sperrregel nach Abrechnung.
Prüfidee: Eine Ticketzeit, die in einer Rechnung abgerechnet wurde, lässt sich auch mit Recht `MOVE_HELPDESK_TIMER` nicht mehr auf ein anderes Ticket verschieben.
Tracelinks: SyRS-013, SyRS-026, SyRS-027; SwRS-011, SwRS-012, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Lagerbestandsführung mit Serien-/Barcodeverfolgung
Ebene: StRS
Typ: funktional
Akteur: Lagerist / Logistik
Vorbedingung: Ein Artikel ist im Artikelstamm angelegt und einem Lager zugeordnet.
Fakt: `ReceiptArticleBookingBL.BookArticles`/`UnBookArticles` verändern Lagerbestände beim Speichern von Belegen; `ValidateArticleWarehouses` prüft die Lagerzuordnung der Positionen. Artikel besitzen das Merkmal `NeedsBarcodes`; `ReceiptBarcodeBL` (98 KB) prüft `CheckBarcodeCountsInTheReceipt`, `CheckIfAllNonActiveBarcodesAreStillInTheReceipt` und `CheckForDuplicateBarcodes`. Für Seriennummernverwaltung existiert der Rechteblock `UserRightsConst.Purchase.StockList.SerialAdministration` mit 7 Rechten (u. a. `ADD_SERIAL_NUMBER`, `REPLACE_SERIAL_NUMBER`, `RESET_SERIAL_NUMBER`).
Aussage: Das System soll Lagerbestände beleggesteuert fortschreiben und für gekennzeichnete Artikel die Erfassung, Zuordnung und Verfolgung von Seriennummern/Barcodes je Belegposition erzwingen.
Ergebnis: Beim Speichern eines bestandsrelevanten Belegs sind die Lagerbestände konsistent fortgeschrieben; für seriennummernpflichtige Artikel ist die Anzahl erfasster Barcodes gleich der Positionsmenge.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3767-3777 (`CheckBarcodeCountsInTheReceipt`, `ValidateArticleWarehouses` – Abbruch bei Fehler) - Begründung: Speichern wird bei unvollständiger Barcodeerfassung oder ungültigem Lager verweigert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3859-3868 (`UnBookArticles`/`BookArticles`) - Begründung: Bestandsfortschreibung ist Teil des Belegspeicherns, nicht optional.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:347-366 (Bestandsdifferenz, `article.NeedsBarcodes`) - Begründung: Zeigt die konkrete Bestandsberechnung und die Sonderbehandlung barcodegeführter Artikel.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1772-1783 (`SerialAdministration`) - Begründung: Serienummernoperationen sind einzeln rechtegeschützt.
Prüfidee: Ein Lieferschein mit einer Position über 3 Stück eines Artikels mit `NeedsBarcodes = true` und nur 2 erfassten Barcodes lässt sich nicht speichern.
Tracelinks: SyRS-017, SyRS-020, SyRS-025; SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Elektronischer Datenaustausch mit Distributoren (EDI)
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer / Lieferant
Vorbedingung: Für den Lieferanten ist eine EDI-Konfiguration (`SupplierEdiConfigurations`) mit Verbindungsdaten hinterlegt.
Fakt: `SupplierEdiBL` (118 KB) ist als partielle Klasse je Distributor aufgeteilt (`.Also`, `.AlsoCH`, `.Alltron`, `.Herweck`, `.Komsa`, `.Opentrans`). Im Verzeichnis `src/backend/Centron.Gateway/` existieren eigenständige Parser-Bibliotheken `EDI_Alltron`, `EDI_Also`, `EDI_AlsoCH`, `EDI_EGIS`, `EDI_Herweck`, `EDI_Komsa`, `OpenTrans`, `OpenTrans1_0`, `ZUGFeRD21_Extended`. Der Hintergrunddienst `EdiDownloadService` ruft EDI-Dateien zyklisch ab.
Aussage: Das System soll Bestellungen elektronisch an Distributoren übermitteln sowie Auftragsbestätigungen, Lieferavise und Rechnungen der Distributoren automatisiert einlesen und den zugehörigen Bestellungen zuordnen.
Ergebnis: Eingelesene EDI-Dokumente aktualisieren die zugehörigen Lieferantenbelege (Mengen, Preise, Termine, Seriennummern) und werden protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs und Partialklassen im selben Verzeichnis - Begründung: Enthält die Verarbeitungslogik je Distributorformat.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EdiDownloadService.cs - Begründung: Belegt den automatisierten, zyklischen Abruf im Serverbetrieb.
- [PRIMÄR] src/backend/Centron.Gateway/ (Unterverzeichnisse EDI_*, OpenTrans*, ZUGFeRD21_Extended) - Begründung: Eigenständige Formatbibliotheken belegen die unterstützten Standards.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:687 (`EDIManagementController`, Recht `RIGHT_EDIMANAGEMENT = 20400343`) - Begründung: EDI-Verwaltung ist ein eigenes, rechtegeschütztes Modul.
- [KONTEXT] docs/reference/edi/edi-architecture.md:114-122 (Matrix Lieferant × Dokumentart) - Begründung: Dokumentiert, welcher Distributor welche Dokumentarten unterstützt.
Prüfidee: Für jeden in `EdiDataType` gelisteten Formattyp existiert eine Leseroutine, die eine Beispieldatei in c-entron-Belegdaten überführt.
Tracelinks: SyRS-034, SyRS-035; SwRS-024
Konsolidierung: Kandidat: Die Verarbeitungspfade je Distributor duplizieren Kopf-/Positions-Mapping; im Zielsystem als ein Mapping-Framework mit formatspezifischen Adaptern zusammenführbar.
Status: belegt
```
```
ID: StRS-010
Titel: Finanzprozesse: Offene Posten, Mahnwesen, Zahlungsverkehr, Buchhaltungsexport
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung
Vorbedingung: Es existieren gebuchte Rechnungen und ein konfiguriertes Kontenrahmen-/Buchhaltungssystem.
Fakt: Es existieren die Module `DunningOverviewAppModuleController`, `OposOverviewAppModuleController`, `PaymentTransactionAppModuleController`, `PaymentsAppModuleController`, `OutgoingPaymentsAppModuleController`, `DatevOnlineAppModuleController`, `AccountSystemsAppModuleController`. `DunningLevel` definiert `None`, `Level1`, `Level2`, `Level3`. `BookKeepingExportBL` (81 KB) implementiert den Buchhaltungsexport. `UserRightsConst.Controlling.Finances` enthält u. a. `Dunning = 10971`, `INCOMING_PAYMENT_TRANSACTIONS = 10980`, `OUTGOING_PAYMENT_TRANSACTIONS = 10981` und den Unterblock `OnlineBanking`.
Aussage: Das System soll offene Posten verwalten, ein dreistufiges Mahnwesen betreiben, Zahlungsein- und -ausgänge verarbeiten und Buchungsdaten an ein externes Finanzbuchhaltungssystem exportieren.
Ergebnis: Zu jedem Kunden ist eine aktuelle Mahnstufe ermittelbar; Buchungsdaten sind in einem für die Finanzbuchhaltung lesbaren Format exportierbar.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/Invoices/Dunning/DunningLevel.cs - Begründung: Definiert die dreistufige Mahnskala als Typ.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningBL.cs, DunningRunBL.cs - Begründung: Implementieren Mahnlaufermittlung und -durchführung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs - Begründung: Implementiert den Buchhaltungsexport.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10228-10249 (`GetCustomerOrSupplierDunningLevel`, Rückgabe 0..3) - Begründung: Bestätigt die dreistufige Skala als geschäftswirksame Größe.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:596-626 (Modulgruppe „Buchhaltung/Finanzen") - Begründung: Zeigt die fachliche Gliederung der Finanzfunktionen.
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/ - Begründung: Belegt die Anbindung eines externen Bankschnittstellenanbieters für Kontoumsätze.
Prüfidee: Für einen Kunden mit überfälliger Rechnung nach Mahnlauf ist `DunningLevel` ≥ 1 und im Modul „Mahnwesen" sichtbar.
Tracelinks: SyRS-024, SyRS-034; SwRS-013, SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Selbstbedienungsportal für Endkunden des Anwenders
Ebene: StRS
Typ: funktional
Akteur: Endkunde des Anwenders (Web-Account)
Vorbedingung: Für einen Ansprechpartner eines aktiven, nicht gesperrten Kunden ist ein Web-Account mit `Status = 1` angelegt.
Fakt: `src/nexus/CentronNexus` ist eine Blazor-Server-Anwendung mit den Bereichen `ServiceBoard` (341 Dateien), `WebCart` (46), `WebOffer` (6), `DocumentSigning` (2), `ProductionOrderManagement` (4), `Office`, `Settings`, `Management`. `WebAccountBL.LoginWithWebAccount` authentifiziert Web-Accounts; `WebAccountRightsConst` definiert Web-Rechte (z. B. `WEBRIGHT_CREATEREQUEST`, `WEBRIGHT_EDITALLREQUESTS`). `ApplicationKind.ServiceBoardOnline` und `ApplicationKind.WebCart` sind eigene lizenzierte Anwendungen.
Aussage: Das System soll Endkunden des Anwenders über ein Webportal ermöglichen, Tickets zu erstellen und zu verfolgen, Artikel aus ihren Sonderpreisen zu bestellen sowie Dokumente einzusehen und zu signieren.
Ergebnis: Ein authentifizierter Web-Account sieht ausschließlich die Daten des ihm zugeordneten Kunden und nur die über Web-Rechte freigegebenen Funktionen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:54-95 (`LoginWithWebAccount`: `Status == 1`, Prüfung Ansprechpartner/Anschrift/Kunde aktiv und nicht gesperrt) - Begründung: Durchgesetzte Zugangsregel des Portals.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-415, 468-479 (`CheckWebRights`, `WebAccountRightsConst.WEBRIGHT_CREATEREQUEST`) - Begründung: Web-Accounts unterliegen einem eigenen, getrennten Rechtemodell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (`CanUserViewReceipt`: „Web-Benutzer haben keine Berechtigung Belege einzusehen.") - Begründung: Belegt die harte Abgrenzung des Portalzugriffs gegenüber dem internen Belegwesen.
- [SEKUNDÄR] README.md:31-36 (WebCart-Beschreibung: „available if you login as a web-account", Artikel aus „Sonderpreise") - Begründung: Beschreibt die fachliche Nutzungsabsicht des WebCart.
- [SEKUNDÄR] src/nexus/CentronNexus.Host/appsettings.json (`Branding.Title = "NEXOWARE ServiceBoard"`, `LoginPageText = "Ihr cleveres Ticketsystem"`) - Begründung: Portalzweck aus der Auslieferungskonfiguration.
Prüfidee: Ein Web-Account, dessen zugeordneter Kunde gesperrt wird, kann sich nicht mehr am Portal anmelden.
Tracelinks: SyRS-006, SyRS-026, SyRS-037, SyRS-038; SwRS-040
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-012
Titel: Gesetzeskonforme elektronische Rechnungsstellung (ZUGFeRD/XRechnung)
Ebene: StRS
Typ: Sicherheit
Akteur: Buchhaltung / Rechnungsempfänger (auch öffentliche Auftraggeber)
Vorbedingung: Die Einstellung `ApplicationSettingID.IsZugferdInvoiceActive` ist aktiviert; für den Empfänger ist ggf. eine Leitweg-ID hinterlegt.
Fakt: `InvoiceZugferdBL` erzeugt XML nach `ZugferdKind` (`ZUGFeRD_1_0`, `ZUGFeRD_XInvoice_1_2`, `_2_0`, `_2_2`, `_2_3_1`, `_3_0_1`). Bei gesetzter `leitwegID` wird `ZugferdFileKind.XInvoice` und die PDF-Konformitätsstufe `PdfZugferdConformanceLevel.XRechnung` verwendet, sonst `Comfort`/`EN16931`. Die XML-Datei wird als `factur-x.xml` (bzw. `ZUGFeRD-invoice.xml` für Version 1.0) in das PDF eingebettet (`AttachZugferdInvoice`). Beim Export wird die UTF-8-BOM entfernt (`stream.ToArray().Skip(3)`).
Aussage: Das System soll Ausgangsrechnungen zusätzlich zum PDF als strukturierten elektronischen Rechnungsdatensatz erzeugen, dabei die konfigurierte ZUGFeRD-/XRechnung-Version verwenden und bei Vorliegen einer Leitweg-ID das XRechnung-Profil anwenden.
Ergebnis: Die erzeugte Rechnungsdatei ist ein PDF/A-3 mit eingebettetem `factur-x.xml` in der konfigurierten Profilstufe; ohne BOM und mit korrekt gesetzter Konformitätsstufe.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:147-165 (`GenerateZugferdFile`, BOM-Entfernung) - Begründung: Erzeugt den strukturierten Datensatz und setzt die Formatregel technisch durch.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:193-212 (`PdfZugferdConformanceLevel.EN16931` vs. `.XRechnung`, `AttachZugferdInvoice`) - Begründung: Belegt die leitweg-abhängige Profilwahl und die PDF-Einbettung.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 (`IsZugferdEnabled` über `ApplicationSettingID.IsZugferdInvoiceActive`) - Begründung: Zeigt die Konfigurierbarkeit als Systemeinstellung.
- [SEKUNDÄR] docs/reference/zugferd-feldzuordnung-anwender.md, docs/reference/zugferd-field-mapping.md - Begründung: Feldzuordnung zwischen c-entron-Daten und ZUGFeRD-Elementen.
- [KONTEXT] docs/guides/development/xrechnung.md:3-4 (Verweis auf ZUGFeRD-2.1.1-Spezifikation) - Begründung: Bestätigt den zugrunde gelegten Standard.
- [KONTEXT] Commit `7d62212022` „Fix: Correct discount calculation to retain sign for ZUGFeRD total check integrity" - Begründung: Belegt, dass Summenkonsistenzprüfungen des Standards praxisrelevant sind.
Prüfidee: Eine mit Leitweg-ID erzeugte Rechnung besteht die Validierung des KOSIT-XRechnung-Prüftools; ohne Leitweg-ID entsteht ein EN16931-konformes ZUGFeRD-PDF.
Tracelinks: SyRS-030; SwRS-015
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-013
Titel: Umsetzung des Löschanspruchs nach DSGVO
Ebene: StRS
Typ: Sicherheit
Akteur: Datenschutzbeauftragter
Vorbedingung: Der Benutzer besitzt das Recht `UserRightsConst.DsgvoModule.DSGVO_DELETE_CONTACT`; das Modul ist lizenziert.
Fakt: `DataSecurityBL.DsgvoDeleteRightDeleteContacts` prüft zunächst `currentUser.HasUserRight(UserRightsConst.DsgvoModule.DSGVO_DELETE_CONTACT)`. Die Löschung erfolgt als Anonymisierung: personenbezogene Felder (Name, Telefon, Fax, E-Mail 1/2, Freitexte, Abteilung, Bild, Active-Directory-SID, Webseite, Web-Benutzername/-Kennwort, Titel) werden auf `null` gesetzt, `Kommentar` wird auf „DSGVO: Auf Anfrage gelöscht. (Durchgeführt von {0} am {1:d} um {1:t} Uhr)" gesetzt und die Felder `IsDsgvoDeleted = true`, `DsgvoDeletedEmployeeI3D`, `DsgvoDeletedDate` werden gefüllt. Jeder gelöschte Feldwert wird zuvor in ein Löschprotokoll geschrieben (`DoAppendDeleteProtocol`).
Aussage: Das System soll auf Antrag einer betroffenen Person deren personenbezogene Daten anonymisieren, den Vorgang mit ausführendem Mitarbeiter und Zeitpunkt kennzeichnen und ein Protokoll der entfernten Werte erzeugen.
Ergebnis: Nach der Verarbeitung enthält der Datensatz keine personenbezogenen Klartextdaten mehr, ist als DSGVO-gelöscht markiert und der Vorgang ist über das Löschprotokoll nachweisbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:787-789 (Rechteprüfung `DSGVO_DELETE_CONTACT`) - Begründung: Durchgesetzte Zugriffsbeschränkung der Löschfunktion.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1195-1275 (Feldweise Anonymisierung, `IsDsgvoDeleted`, `DsgvoDeletedEmployeeI3D`, `DsgvoDeletedDate`, `DoAppendDeleteProtocol`) - Begründung: Zeigt Umfang und Nachweisführung der Anonymisierung im Detail.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:26-27 (Konstanten `DsgvoDeletedContactMessage`) - Begründung: Standardisierter Kennzeichnungstext.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:460-462 (Modul „c-entron DSGVO", Recht `ACCESS_DSGVO_MODULE`, Lizenz `CentronDSGVO`) - Begründung: DSGVO-Funktionen sind ein eigenes, rechte- und lizenzgeschütztes Modul.
Prüfidee: Nach DSGVO-Löschung eines Ansprechpartners enthält der Datensatz in allen personenbezogenen Feldern `NULL` oder den Standardtext; das Löschprotokoll listet jeden zuvor belegten Feldwert.
Tracelinks: SyRS-028; SwRS-016
Konsolidierung: Kandidat: Die Anonymisierungslogik ist in `DataSecurityBL` für mindestens drei Datenmodelle (Kunden-Ansprechpartner, Accounts-Ansprechpartner, Kreditoren-Ansprechpartner) getrennt implementiert; im Zielsystem zu einer generischen, deklarativ konfigurierten Anonymisierung zusammenführbar.
Status: belegt
```
```
ID: StRS-014
Titel: Nachvollziehbarkeit von Änderungen (Belegversionierung und Änderungsprotokolle)
Ebene: StRS
Typ: nicht-funktional
Akteur: Anwenderunternehmen / Wirtschaftsprüfung
Vorbedingung: Ein Beleg oder ein protokollierter Stammdatensatz wird geändert.
Fakt: Jeder Beleg trägt `Version`; `ReceiptBL.CreateNewVersion` setzt `receipt.Version = currentReceiptVersion.Version + 1`, und `SaveReceipt` akzeptiert ausschließlich `Version == 1` (Erstversion), `== previousVersion.Version` oder `== previousVersion.Version + 1` – andernfalls „Der Beleg hat keine gültige Versionsnummer.". Alte Versionen werden in eigene Versionstabellen (`*KopfVersions`/`*PosVersions`) kopiert. Zusätzlich schreibt der NHibernate-Listener `ChangeTrackingEventListener` (`IPreUpdateEventListener`) für attributierte Entitäten je geändertem Feld einen `ChangeLog`-Eintrag mit `ObjectI3D`, `ObjectKind`, `Property`, `OldValue`, `NewValue`, `Date`, `AppUser`. Rechteänderungen werden separat in `AppRightLog` protokolliert.
Aussage: Das System soll Änderungen an Belegen versionsbasiert und Änderungen an gekennzeichneten Stammdatenfeldern feldgenau mit Benutzer und Zeitpunkt protokollieren, sodass jeder Stand rekonstruierbar bleibt.
Ergebnis: Zu jedem Beleg existiert eine lückenlose Versionshistorie; zu jedem protokollierten Feld existiert ein Änderungseintrag mit Alt-/Neuwert, Zeitpunkt und Benutzer.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3568-3578 (Versionsnummernvalidierung mit Fehlermeldung) - Begründung: Erzwingt eine lückenlose Versionsfolge.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3117 (`receipt.Version = currentReceiptVersion.Version + 1`) und 3621-3634 (`SaveReceiptVersion(receipt, previousReceiptVersion)`) - Begründung: Zeigt Erzeugung und Wegschreiben der Vorgängerversion.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-142 - Begründung: Implementiert das feldgenaue Änderungsprotokoll als ORM-Interceptor, also unabhängig vom aufrufenden Anwendungsfall.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:762-857 (`AppRightLog`, Kinds `AddRightToGroup`, `RemoveRightFromGroup`, `AddUserToGroup`, …) - Begründung: Separates Protokoll für sicherheitsrelevante Rechteänderungen.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 (Versionstabellen als 1:1-Kopien) - Begründung: Erläutert die Persistenzstrategie der Versionierung.
Prüfidee: Nach dreimaliger Änderung eines Angebots existieren in `AngKopfVersions` zwei Vorgängerversionen mit fortlaufenden Versionsnummern und der aktuelle Beleg trägt `Version = 3`.
Tracelinks: SyRS-016, SyRS-017, SyRS-036, SyRS-046, SyRS-047; SwRS-008, SwRS-017, SwRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-015
Titel: Kreditlimit- und Mahnstufensteuerung im Vertriebsprozess
Ebene: StRS
Typ: funktional
Akteur: Innendienst / Kreditmanagement
Vorbedingung: Für den Kunden ist ein Kreditlimit (`CreditLimit`) und eine Berechnungsart (`CreditLimitCalculationKind`) hinterlegt.
Fakt: `ReceiptBL.CheckIfCustomerLimitIsReached` summiert über alle limitrelevanten Belegarten das verbrauchte Limit, zieht das Limit der Vorgängerversion ab und meldet bei Überschreitung `ShowCustomerLimitExceededDialog` mit einer Meldung, die Limit, Überschreitungsbetrag und Verbrauch je Belegart nennt; gespeichert wird nur bei `data.SaveAlthoughCustomerLimitExceeded == true`. Die Berechnung erfolgt netto (`CreditLimitCalculationKind == 1`) oder brutto; bei `CreditLimitCalculationKind == null || == 2 || CreditLimit <= 0` findet keine Prüfung statt. Unabhängig davon blockiert `CanUserCreateNewReceiptsAtCustomerOrSupplier` das Anlegen neuer Belege, wenn die Mahnstufe des Kunden die belegartspezifische Sperrstufe erreicht; das Recht `IGNORE_DUNNING_BLOCKING_FOR_RECEIPTS = 20400085` hebt dies auf.
Aussage: Das System soll vor dem Speichern eines limitrelevanten Kundenbelegs prüfen, ob das Kreditlimit des Kunden überschritten wird, und den Vorgang nur nach ausdrücklicher Bestätigung fortsetzen; bei erreichter Mahnstufe soll das Anlegen neuer Belege gesperrt werden.
Ergebnis: Bei Limitüberschreitung erscheint eine Rückfrage mit beziffertem Überschreitungsbetrag; bei erreichter Sperr-Mahnstufe wird das Anlegen mit belegartbezogener Meldung abgelehnt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:8636-8690 (`CheckIfCustomerLimitIsReached`) - Begründung: Vollständige, durchgesetzte Limitregel inkl. Netto/Brutto-Unterscheidung und Ausnahmebedingungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10205-10216 (Mahnstufensperre, `BlockNewReceiptsDunningLevel`) - Begründung: Durchgesetzte Sperrregel bei Mahnstufe.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2157-2161 (`IGNORE_DUNNING_BLOCKING_FOR_RECEIPTS` mit deutschsprachiger Rechtebeschreibung) - Begründung: Beschreibt die Ausnahmeberechtigung fachlich.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2404 (`EDIT_LIMIT_CUSTOMER`) - Begründung: Die Limitpflege ist eigenständig rechtegeschützt.
Prüfidee: Ein Auftrag, der das Restlimit eines Kunden um 100 EUR überschreitet, führt zu einer Rückfrage, deren Text den Betrag 100,00 und den Verbrauch je Belegart ausweist; ohne Bestätigung wird nicht gespeichert.
Tracelinks: SyRS-017, SyRS-021; SwRS-013, SwRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Provisionsermittlung für Vertriebsmitarbeiter
Ebene: StRS
Typ: funktional
Akteur: Außendienst / Vertriebsleitung
Vorbedingung: Ein Provisionsschema ist angelegt und einem Kunden zugeordnet.
Fakt: Es existieren die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`, `ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionItemEntity`, `ReceiptProvisionEmployeeGoal`, `ReceiptProvisionEmployeeLevel` sowie `ReceiptProvisionBL` (45 KB) und `ReceiptProvisionSchemaBL` (29 KB). `ReceiptBL` ruft beim Laden `_receiptProvisionBL.FillReceiptWithProvision(receipt)` auf. Der Rechteblock `UserRightsConst.Sales.Provision` umfasst `PROVISION_EVALUATION_MODULE`, `PROVISION_EVALUATION_ONLY_OWN`, `PROVISION_SCHEMA_MANAGEMENT`, `PROVISION_SCHEMA_CUSTOMER_ASSIGNMENT`, `CAN_SEE_ALL_PROVISION_IN_RECEIPTS`, `PROVISION_EVALUATION_ONLY_OWN_BRANCH`. Der Hintergrunddienst `UpdateExpiredProvisionSchemasService` läuft stündlich.
Aussage: Das System soll je Beleg Provisionsbeträge nach kundenbezogen zugeordneten Provisionsschemas ermitteln und die Auswertung wahlweise auf die eigenen Vorgänge bzw. die eigene Filiale beschränken.
Ergebnis: Zu jedem provisionsrelevanten Beleg sind Provisionswerte je Position ermittelt; die Provisionsauswertung zeigt Benutzern ohne erweitertes Recht nur eigene Werte.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptProvisionBL.cs; src/backend/Centron.BL/Sales/Receipts/ReceiptProvisionSchemaBL.cs - Begründung: Implementieren Schemaverwaltung und Provisionsberechnung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7250 (`FillReceiptWithProvision`) - Begründung: Provisionsdaten sind fester Bestandteil des Belegladens.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2443-2453 (Provisionsrechte) - Begründung: Durchgesetzte Sichtbarkeitsabstufung.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs:45 (`TimeSpan.FromHours(1)`) - Begründung: Belegt die zeitliche Gültigkeit von Provisionsschemas und deren automatische Fortschreibung.
Prüfidee: Ein Benutzer mit `PROVISION_EVALUATION_ONLY_OWN` sieht in der Provisionsauswertung ausschließlich Belege, bei denen er als Betreuer eingetragen ist.
Tracelinks: SyRS-013; SwRS-020
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: Auswertungen und Kennzahlen für die Unternehmenssteuerung
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung / Controlling
Vorbedingung: Der Benutzer besitzt das jeweilige Statistikrecht.
Fakt: `UserRightsConst.Controlling.Analytics` definiert je Auswertungsart ein eigenes Recht: `SALES_STATISTIC`, `PURCHASE_STATISTIC`, `TICKET_STATISTIC`, `CONTRACT_STATISTIC`, `EMPLOYEE_STATISTIC`, `OFFER_STATISTIC`, `SALE_PURCHASE_ARTICLE_STATISTIC` sowie das einschränkende Recht `SHOW_ONLY_STATISTIC_FROM_OWN_BRANCH = 20800145`. Der Ordner `src/backend/Centron.BL/Statistics` enthält 16 Dateien, `Centron.Entities/Entities/Statistics` 35. Module: `SaleStatisticsAppModuleController`, `EmployeeAnalyticsAppModuleController`, `ManagementInfoAppModuleController`, `ContractEvaluation2AppModuleController`, `MspDashboardAppModuleController`.
Aussage: Das System soll Auswertungen zu Umsatz, Einkauf, Tickets, Verträgen, Mitarbeitern und Angeboten bereitstellen, deren Zugriff je Auswertungsart einzeln berechtigt und optional auf die eigene Filiale beschränkt werden kann.
Ergebnis: Ein Benutzer sieht ausschließlich die Auswertungen, für die er das jeweilige Recht besitzt; mit dem Filialrecht sind die Kennzahlen auf seine Filiale reduziert.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2574-2586 (`Controlling.Analytics`) - Begründung: Je Auswertungsart eigenes, durchgesetztes Recht.
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/README.md:12-19 – Beispiel `[AuthorizeUserRight(UserRightsConst.Controlling.Analytics.SALES_STATISTIC)]` - Begründung: Zeigt die Durchsetzung des Statistikrechts auch an der modernen REST-Schnittstelle.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs:628-670 (Modulgruppe „Controlling/Analytics") - Begründung: Bestätigt die Auswertungen als eigenständige Fachmodule.
Prüfidee: Ein Benutzer ohne `TICKET_STATISTIC` erhält beim Aufruf der Ticketstatistik über die REST-Schnittstelle HTTP 403.
Tracelinks: SyRS-009, SyRS-013; SwRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Deutschsprachige Anwenderoberfläche mit optionaler englischer Sprachfassung
Ebene: StRS
Typ: nicht-funktional
Akteur: Endanwender
Vorbedingung: –
Fakt: Die Basis-Ressourcendateien enthalten deutschsprachige Texte (`LocalizedStrings.resx`), die englische Fassung liegt als `LocalizedStrings.en.resx` vor. Umfang: WPF-Client 404 KB (de) / 349 KB (en), `Centron.Controls` 129 KB / 125 KB, `Centron.BL` 26 KB / 24 KB. Das Blazor-Portal nutzt `SharedResource.resx` / `SharedResource.en-US.resx` sowie `WebCartResource.resx` / `.en-us.resx`. Fehlermeldungen im Backend sind deutschsprachig (z. B. „Der Beleg hat kein gültiges Datum.", „Die maximale Anzahl an Lizenzen wurde erreicht.").
Aussage: Das System soll alle anwendersichtbaren Texte in deutscher Sprache als Standardsprache bereitstellen und zusätzlich eine englische Sprachfassung über getrennte Ressourcendateien unterstützen.
Ergebnis: Jeder anwendersichtbare Text ist in Deutsch verfügbar; für Texte mit englischer Übersetzung wird bei englischer Spracheinstellung die englische Fassung angezeigt.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Resources/LocalizedStrings.resx (404 KB, deutsch) und LocalizedStrings.en.resx (349 KB) - Begründung: Belegt Standardsprache Deutsch und die zweisprachige Auslegung samt Umfangsdifferenz.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3565, 3577 (deutschsprachige Fehlermeldungen direkt im Code) - Begründung: Zeigt, dass Deutsch auch in nicht lokalisierten Codepfaden die Ausgabesprache ist.
- [SEKUNDÄR] ResXManager.config.xml - Begründung: Werkzeugkonfiguration für die Ressourcenpflege.
- [KONTEXT] docs/getting-started/general-structure.md:114-141 („German-First Language Policy") - Begründung: Formuliert die Sprachvorgabe als Projektregel.
Prüfidee: Für jeden Schlüssel in `LocalizedStrings.en.resx` existiert ein Schlüssel in `LocalizedStrings.resx`; Stichprobe von 20 Oberflächentexten ist deutschsprachig.
Tracelinks: SyRS-048; SwRS-022, SwRS-036
Konsolidierung: nein
Status: belegt; Workaround (Die Umfangsdifferenz von rund 55 KB zwischen deutscher und englischer WPF-Ressourcendatei sowie deutschsprachige Literale direkt im Backend-Code deuten auf eine unvollständige Lokalisierung hin – im Zielsystem zu vereinheitlichen.)
```
```
ID: StRS-019
Titel: Betrieb wahlweise als Windows-Installation oder containerisiert
Ebene: StRS
Typ: nicht-funktional
Akteur: IT-Betrieb des Anwenderunternehmens
Vorbedingung: Eine SQL-Server-Datenbank ist erreichbar.
Fakt: Es existieren WiX-Installationsprojekte (`deployment/centron/CentronSetupProject`, `WebServiceSetupProject`, `WixSharpInstaller`) für Windows. Parallel existieren Dockerfiles für `c-entron-api`, `c-entron-webservice`, `c-entron-demo`, `c-entron-mailcatcher` sowie eine `compose.yaml`, die die Dienste `db` (MSSQL), `webservice` (`/app/Centron.Host.Console`, Port 1234→4321), `smtp` und `nexus` (Port 8050) in einem Bridge-Netzwerk startet. `Centron.BL` zielt auf `net10.0;net10.0-windows`, `Centron.Host` und `Centron.DAO` auf `net10.0` (plattformneutral); nur `Centron.WPF.UI` ist auf `net10.0-windows` mit `UseWPF` festgelegt.
Aussage: Das System soll den Web-Service und das Webportal sowohl als Windows-Dienst als auch als plattformneutrale Container-Anwendung betreibbar machen; die WPF-Clientanwendung bleibt Windows-gebunden.
Ergebnis: Der Web-Service ist über `Centron.Host.Console` unter Linux/Container lauffähig und über HTTP bzw. HTTPS erreichbar; der Windows-Betrieb erfolgt über `Centron.Host.WindowsService`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Centron.BL.csproj (`<TargetFrameworks>net10.0;net10.0-windows</TargetFrameworks>`) und src/webservice/Centron.Host/Centron.Host.csproj (`net10.0`) - Begründung: Die Multi-Targeting-Konfiguration ist die technische Voraussetzung für plattformneutralen Serverbetrieb.
- [PRIMÄR] docker/compose/compose.yaml (Dienste db/webservice/smtp/nexus, Volumes für `WebServiceConfig.xml` und `appsettings.Production.json`, `restart: on-failure`) - Begründung: Vollständige, ausführbare Betriebsbeschreibung.
- [PRIMÄR] deployment/centron/WebServiceSetupProject/Product.wxs, deployment/WixSharpInstaller/Program.cs - Begründung: Belegt den alternativen Windows-Installationsweg.
- [KONTEXT] docs/guides/services/web-service-on-linux.md:8-92 (Installation, HTTPS über pfx, systemd-Unit) - Begründung: Beschreibt den Linux-Betrieb einschließlich bekannter Einschränkungen.
Prüfidee: `docker compose up` startet Datenbank, Web-Service und Portal; der Web-Service antwortet auf Port 4321, das Portal auf Port 8050.
Tracelinks: SyRS-039, SyRS-040, SyRS-041, SyRS-043; SwRS-023, SwRS-033, SwRS-034, SwRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Anbindung externer Artikel- und Preisquellen
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkäufer / Vertriebsinnendienst
Vorbedingung: Zugangsdaten für die jeweilige externe Quelle sind konfiguriert.
Fakt: Unter `src/apis/` existieren eigenständige Zugriffsbibliotheken für ITscope (`Centron.APIs.ITscopeDataAccess`), Icecat (`Centron.APIs.IcecatDataAccess`), COP (`Centron.APIs.CopDataAccess`), EGIS (`Centron.APIs.EgisDataAccess`), FinAPI, GLS und Shipcloud. Im Belegkontext existieren die Artikelsuch-Provider `ITscopeExternalArticleSearchProvider`, `EgisExternalArticleSearchProvider`, `CopApiBaseExternalArticleSearchProvider`. Zusätzlich existiert die interne Preisquelle „Aktionspreise" (`ActionPriceBL`, Tabelle `HerstellerArtikAktionspreis`).
Aussage: Das System soll Artikelstammdaten, Verfügbarkeiten und Einkaufspreise aus mehreren externen Quellen parallel abrufen und dem Anwender in einer vergleichenden Preisübersicht („Preisspiegel") gemeinsam mit internen Aktionspreisen darstellen.
Ergebnis: Der Preisspiegel eines Artikels enthält je verfügbarer Quelle mindestens Lieferant, Einkaufspreis, Datum und – soweit vorhanden – Verfügbarkeit.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ArticleSearch/ITscopeExternalArticleSearchProvider.cs, EgisExternalArticleSearchProvider.cs, CopApiBaseExternalArticleSearchProvider.cs - Begründung: Implementieren den parallelen Abruf externer Artikel-/Preisdaten im Belegkontext.
- [PRIMÄR] src/apis/ (7 eigenständige Integrationsprojekte) - Begründung: Belegt die abgegrenzten externen Schnittstellen.
- [SEKUNDÄR] docs/reference/receipts/actionprice-system.md:185-193 (Aufzählung der sieben parallelen Preisquellen) - Begründung: Beschreibt die fachliche Zusammenführung im Preisspiegel.
- [KONTEXT] docs/reference/receipts/actionprice-system.md:299-312 (Validierungs- und Anzeigeregeln der Aktionspreise) - Begründung: Ergänzt die Gültigkeitsregel „Datum innerhalb Gültigkeitszeitraum".
Prüfidee: Für einen Artikel mit Herstellernummer, für den in zwei externen Quellen Preise existieren, enthält der Preisspiegel mindestens zwei Zeilen mit unterschiedlichem Quellenkennzeichen.
Tracelinks: SyRS-034; SwRS-024
Konsolidierung: Kandidat: Sieben Preisquellen mit je eigener Abruf-, Parsing- und Anzeigelogik; im Zielsystem als ein Provider-Interface mit einheitlichem Ergebnismodell zusammenführbar.
Status: belegt
```
```
ID: StRS-021
Titel: Nutzungsbasierte Abrechnung von Managed Services (RMM/MSP)
Ebene: StRS
Typ: funktional
Akteur: Managed-Service-Provider (Anwenderunternehmen)
Vorbedingung: Der Vertrag ist für RMM-Abrechnung konfiguriert und die RMM-Schnittstelle ist erreichbar.
Fakt: `AutomaticFacturaWebServiceBL.CheckRMMArticle` sucht in den Rechnungspositionen den Platzhalter `@@RMMArtikel@@` (in `RichText` oder `Text`), ruft Nutzungsdaten für den Abrechnungszeitraum ab und fügt daraus Positionen ein. Ist der RMM-Dienst nicht erreichbar und werden RMM-Artikel erwartet, wird `RMMServiceUnavailableException` geworfen und die Rechnungserstellung abgebrochen. Der Platzhalter ist in `VariablesCollection.cs:73` als offizielle Variable registriert. Zusätzlich existieren die Module `MspCollectorAppModuleController`, `MSPComparerAppModuleController`, `MspDashboardAppModuleController` mit eigenem Rechteblock `UserRightsConst.MspCollector`.
Aussage: Das System soll aus einem externen Monitoring-/RMM-System periodische Nutzungsmengen beziehen und daraus Rechnungspositionen erzeugen; ist der Bezug nicht möglich, soll keine unvollständige Rechnung entstehen.
Ergebnis: Bei erreichbarem RMM-Dienst enthält die Vertragsrechnung eine Position je genutztem Leistungsmerkmal; bei nicht erreichbarem Dienst wird die Rechnungserstellung mit Fehlermeldung abgebrochen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:721-726, 800, 2412-2414 (`CheckRMMArticle`, `throw new RMMServiceUnavailableException`) - Begründung: Setzt die Regel „keine Rechnung ohne vollständige Nutzungsdaten" technisch durch.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/Variables/VariablesCollection.cs:73 (`"@@RMMArtikel@@"`) - Begründung: Der Platzhalter ist ein definiertes Konfigurationsmerkmal, kein Zufallstext.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2621-2628 (`MspCollector`) - Begründung: MSP-Auswertung ist eigenständig berechtigt.
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md:46-52 („This prevents invoices from being created with incomplete usage data, ensuring customers are billed correctly.") - Begründung: Formuliert die fachliche Absicht der Abbruchregel.
Prüfidee: Bei simulierter Nichterreichbarkeit des RMM-Dienstes und mindestens einer konfigurierten RMM-Artikelreferenz entsteht keine Rechnung; im Protokoll steht die RMM-Fehlermeldung.
Tracelinks: SyRS-029, SyRS-034; SwRS-009, SwRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Mehrstufige Authentifizierung und Anbindung an Unternehmens-Identitätsdienste
Ebene: StRS
Typ: Sicherheit
Akteur: IT-Sicherheitsverantwortlicher des Anwenderunternehmens
Vorbedingung: Die Authentifizierungsverfahren sind in `WebServiceConfig.xml` bzw. den Anwendungseinstellungen konfiguriert.
Fakt: `AuthenticatorFactory` wählt anhand von `SystemAuthenticationMethod` (`None`, `Basic`, `ActiveDirectory`, `OpenIdConnect`) den Authentifikator. OpenID Connect setzt die Lizenz `LicenseGuids.OpenIDConnectAuthentication` und die aktivierte JWT-Einstellung voraus. Zusätzlich prüft `TwoFactorAuthBL.ValidateTwoFactor` bei aktivem `TwoFactorAuthEnabled` einen zweiten Faktor über `RadiusServer` oder `EmailLink`; die Gültigkeitsdauer wird je Benutzer (`TwoFactorValidDurationInDays`) oder global gesetzt, wobei `0` bedeutet: bei jeder Anmeldung.
Aussage: Das System soll die Benutzeranmeldung wahlweise gegen den internen Benutzerstamm, gegen Active Directory oder gegen einen OpenID-Connect-Anbieter durchführen und optional einen zweiten Authentifizierungsfaktor per RADIUS oder E-Mail-Bestätigung erzwingen.
Ergebnis: Bei aktivierter Zwei-Faktor-Authentifizierung und abgelaufener Gültigkeit muss der Benutzer den zweiten Faktor erneut bestätigen, bevor ein Sitzungsticket ausgestellt wird.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:88-146 (Auswahl des Authentifikators, Lizenz- und Aktivierungsprüfung für OpenID Connect) - Begründung: Zentrale, durchgesetzte Verfahrenswahl.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs:33-135 (`ValidateTwoFactor`, `HasToValidateTwoFactor`, tagesbasierte Gültigkeit) - Begründung: Vollständige Regel für die Notwendigkeit des zweiten Faktors.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs:183-193 (`TwoFactorAuthType.RadiusServer` / `.EmailLink`) - Begründung: Abschließende Aufzählung der zweiten Faktoren.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:62-70 (Abbruch der Anmeldung bei fehlgeschlagener 2FA) - Begründung: Beweist die Durchsetzung im Anmeldepfad.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml (`TwoFactorAuthEnabled`, `TwoFactorAuthType`, `RadiusServer*`, `MailTwoFactorAuthTimeoutInSeconds`, `TwoFactorValidDurationInDays`) - Begründung: Zeigt die Konfigurationsparameter der Auslieferung.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md - Begründung: Beschreibt die Microsoft-/Entra-ID-Anbindung fachlich.
Prüfidee: Bei `TwoFactorValidDurationInDays = 0` und aktivem 2FA wird bei jeder Anmeldung ein zweiter Faktor angefordert; bei Wert 1 nur einmal je Kalendertag je Kombination aus Benutzer, Anwendung, Maschine und IP-Adresse.
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SyRS-004; SwRS-025, SwRS-026
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-023
Titel: Dokumentenverwaltung und rechtsgeschäftliche Signatur (C-Sign)
Ebene: StRS
Typ: funktional
Akteur: Vertrieb / Kunde
Vorbedingung: Ein Dokument (z. B. Web-Angebot) ist über einen Token für den Empfänger freigegeben.
Fakt: Es existieren die Objektarten `DocumentSigning = 7600133` und `DocumentSigningCustomerReceipts = 7600146`. Im Portal existieren `DocumentSigningPage.razor` und `IsolatedSignaturePad.razor`. Die Legacy-REST-Schnittstelle stellt `GetSharedDocumentByToken`, `SharedDocumentAccepted` und `SignSharedDocument` bereit – jeweils **ohne** `[Authenticate]`-Attribut, also tokenbasiert und ohne Sitzungsanmeldung. Zusätzlich existieren Dokumentenrechte `UserRightsConst.Sales.Documents` (`READ_DOCUMENTS`, `ADD_DOCUMENTS`, `CHANGE_DOCUMENTS`, `DELETE_DOCUMENTS`, Verzeichnisrechte) und der Objekttyp `WebOffer = 7600126`.
Aussage: Das System soll Dokumente an einer Objekt-/Verzeichnisstruktur verwalten und ausgewählte Dokumente über einen zeitlich und inhaltlich begrenzten Token einem externen Empfänger zur Ansicht, Annahme und handschriftlichen Signatur bereitstellen.
Ergebnis: Ein Empfänger kann ein per Token freigegebenes Dokument ohne Benutzerkonto öffnen, annehmen und signieren; die Annahme/Signatur wird am Objekt festgehalten.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetSharedDocumentByToken`, `SharedDocumentAccepted`, `SignSharedDocument`, jeweils ohne `[Authenticate]`) - Begründung: Belegt den bewusst anonymen, tokengesicherten Zugang.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:231, 255 (`DocumentSigning`, `DocumentSigningCustomerReceipts`) - Begründung: Signaturvorgänge sind eigenständige, referenzierbare Objektarten.
- [PRIMÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor - Begründung: Implementiert die Signaturerfassung im Portal.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1884-1901 (`Sales.Documents`) - Begründung: Dokumenten- und Verzeichnisoperationen sind einzeln rechtegeschützt.
- [KONTEXT] Commits `89ccfd650d` „Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)", `cf27c00580` „Ticket 160807 - Fix c-sign document preview and signing document" - Begründung: Belegen C-Sign als aktiv weiterentwickelte Fachfunktion und benennen die Ticketreferenzen.
Prüfidee: Ein gültiger Dokumententoken erlaubt Aufruf und Signatur ohne Anmeldung; nach Signatur ist der Vorgang am zugehörigen Beleg dokumentiert und der Token nicht erneut zur Signatur verwendbar.
Tracelinks: SyRS-010, SyRS-011; SwRS-027
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Anpassbarkeit des Systemverhaltens ohne Programmierung
Ebene: StRS
Typ: nicht-funktional
Akteur: Systemadministrator (Anwenderseite)
Vorbedingung: Der Benutzer besitzt das Recht `UserRightsConst.Administration.SETTINGS`.
Fakt: Es existieren zwei Einstellungsspeicher: die Legacy-Tabelle `Stammdat` mit 728 Konstanten in `AppSettingsConst` und die aktuelle Tabelle `ApplicationSettings` mit 492 Einträgen in `ApplicationSettingID` (nächste freie ID laut Kopfkommentar: 10471). Beide werden über `AppSettingsBL.GetSettings(...)` typisiert gelesen (`GetBool`, `GetInt`, `GetString`, `GetLargeString`, `GetEnum<T>`, `GetDecimal`). `ApplicationSettingDefinitions.cs` (85 KB) hält je Einstellung eine Beschreibung.
Aussage: Das System soll sein fachliches Verhalten (Pflichtfelder, Vorbelegungen, Textbausteine, Formate, Schnittstellenschalter, Automatisierungen) über zentral verwaltete, typisierte Anwendungseinstellungen konfigurierbar machen.
Ergebnis: Eine Verhaltensänderung wie „ZUGFeRD-Rechnung aktiv" oder „Ticket-Kurzbeschreibungspräfix" ist ohne Codeänderung über die Einstellungen erreichbar und wirkt nach dem Speichern.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs (492 Einträge, Kopfkommentar mit ID-Verwaltung) - Begründung: Zentrale, im Code durchgesetzte Registratur der Einstellungen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Settings/AppSettingsConst.cs (728 Einträge) - Begründung: Belegt den parallelen Legacy-Speicher.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:351-374 (`AddShortDescriptionPrefix` liest `IsHelpdeskShortDescriptionPrefixActivated` und `HelpdeskShortDescriptionPrefix` und ersetzt Variablen) - Begründung: Konkretes Beispiel einstellungsgesteuerten Fachverhaltens.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 - Begründung: Zweites Beispiel: Schnittstellenaktivierung per Einstellung.
- [KONTEXT] docs/guides/development/settings-management.md:7-47 - Begründung: Beschreibt die Zweiteilung der Einstellungsspeicher und die ID-Verwaltung.
Prüfidee: Das Umschalten von `IsZugferdInvoiceActive` verändert ohne Neustart des Clients das Ergebnis von `IsZugferdEnabled()` und damit die Rechnungsausgabe.
Tracelinks: SyRS-049; SwRS-028, SwRS-034
Konsolidierung: Kandidat: Zwei parallele Einstellungsspeicher (`Stammdat` / `ApplicationSettings`) bilden dieselbe fachliche Funktion ab; im Zielsystem zwingend zusammenzuführen.
Status: belegt; Workaround (Die Doppelung `Stammdat`/`ApplicationSettings` ist laut Projektdokumentation historisch bedingt; neue Einstellungen dürfen nur noch in `ApplicationSettings` angelegt werden.)
```
```
ID: StRS-025
Titel: Automatisierter, unbeaufsichtigter Hintergrundbetrieb
Ebene: StRS
Typ: funktional
Akteur: IT-Betrieb / Anwenderunternehmen
Vorbedingung: Der Web-Service läuft und die Ausführung von Diensten ist aktiviert (`ExecuteServices`).
Fakt: Der Web-Service-Host registriert 35 Hintergrunddienste (`src/webservice/Centron.Host/AspNetCore/HostedServices/`), darunter `EdiDownloadService`, `EscalationsService`, `ContractEndeService`, `ContractCloseService`, `ReminderService`, `MassUpdateService`, `DataQualityService`, `ExchangeSyncService`, `TelemetryUploadService`, `ArticleImportService`, `AutomaticPriceUpdateService`, `GfkExportService`, `PlmImportService`, `SendMyDayNotificationsService`, `TaskManagmentService`. Alle erben von `ManagedBackgroundService`, das je Dienst über `BackgroundServiceBL.IsServiceEnabled(serviceName)` aktivierbar ist und Start-/Laufzeiten protokolliert. Die Konfiguration `ExecuteServices` in `WebServiceConfig.xml` steuert die Ausführung insgesamt.
Aussage: Das System soll wiederkehrende fachliche Aufgaben (EDI-Abruf, Vertragsende- und -abschlussprüfung, Eskalationen, Erinnerungen, Massenänderungen, Datenqualitätsprüfungen, Kalendersynchronisation, Importe) ohne Benutzerinteraktion zeitgesteuert ausführen und je Aufgabe einzeln aktivierbar machen.
Ergebnis: Für jeden aktivierten Dienst sind Startzeit und letzte Laufzeit im System hinterlegt; deaktivierte Dienste werden übersprungen und protokolliert.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-94 (`UpdateStartTime`, `GetIsEnabledCached`, `UpdateLastRunTime`) - Begründung: Einheitliches, durchgesetztes Ausführungs- und Steuerungsmodell aller Hintergrunddienste.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ (35 Dienstklassen) - Begründung: Belegt Umfang und Art der automatisierten Aufgaben.
- [SEKUNDÄR] docker/compose/WebServiceConfig.xml (`<ExecuteServices>false</ExecuteServices>`) - Begründung: Globaler Schalter der Dienstausführung in der Auslieferungskonfiguration.
- [KONTEXT] docs/Background Service/DataQualityService.md:4-21 - Begründung: Beschreibt Zweck und Taktung eines Beispieldienstes fachlich.
Prüfidee: Wird ein Dienst über `BackgroundServiceBL` deaktiviert, protokolliert der Host innerhalb von 60 Sekunden „… is disabled, skipping execution." und führt keine fachliche Aktion aus.
Tracelinks: SyRS-035, SyRS-045; SwRS-029, SwRS-033, SwRS-037
Konsolidierung: nein
Status: belegt
```
---
## 3. Abgrenzung
Nicht Gegenstand dieser StRS sind:
- Anforderungen an die Delphi-Vorgängeranwendung „c-entron Delphi". Sie wird im Code nur noch als Lizenz-/Versionssonderfall behandelt (`LicenseManager.TryFixCentronDelphiVersionNumber`) und ist nicht Teil des Arbeitsverzeichnisses.
- Als `[Obsolete]` gekennzeichnete Funktionsbereiche (u. a. `UserRightsConst.Monitoring`, `.SupRemo`, `.DirectNow`, `.Riversuite`, `.N13`, `Sales.Cashbox`). Sie sind im Code vorhanden, aber ausdrücklich abgekündigt und werden im Zielsystem nicht benötigt. Siehe `Analysebericht.md`, Abschnitt „Bekannte Lücken".
@@ -0,0 +1,860 @@
# SwRS – Software Requirements Specification
**System:** NEXOWARE c-entron ERP
**Verfahren:** Reverse Requirements Engineering (statische Artefaktanalyse), ISO/IEC/IEEE 29148:2018
**Analysebasis:** Git-Arbeitskopie `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Commit `79c1142f48` (Stand 2026-08-25)
**Erstellt:** 2026-08-25 · **Iteration:** V1 Baseline (Prompt-only), Lauf 01
---
## 0. Zweck dieser Ebene
Die SwRS beschreibt die softwareinternen Strukturen: Komponentenschnitt, Datenmodellkonventionen, softwareinterne Regeln und Persistenzmechanismen. Sie ist die Ebene, auf der die Neuimplementierung entscheiden muss, **welche Struktur übernommen und welche abgelöst wird**. Anforderungen, die eine erkennbar historische Lösung beschreiben, tragen im Feld `Status` den Zusatz `Workaround`.
---
## 1. Architektur und Komponentenschnitt
```
ID: SwRS-001
Titel: Sechsschichtige Anwendungsarchitektur
Ebene: SwRS
Typ: funktional
Akteur: Gesamtsystem
Vorbedingung: Eine Fachfunktion wird vom Client aufgerufen.
Fakt: Die Codebasis ist in sechs Schichten mit je eigenem Objekttyp gegliedert: UI (`Centron.WPF.UI`, `CentronNexus`) → ViewModel (DTO/ViewModel) → `ILogic`/`BL*Logic`/`WS*Logic` (DTO) → `ICentronRestService`/`CentronRestService` (DTO) → `*WebServiceBL` (Entity↔DTO-Wandlung, AutoMapper-Profile unter `Centron.BL/WebServices/ObjectMapperConfiguration/`) → `*BL` (Entity, NHibernate) → Datenbank. `Centron.BL/WebServices` enthält 464 Dateien, `Centron.BL` insgesamt über 2 100.
Aussage: Das System soll den Datenfluss zwischen Oberfläche und Datenbank über klar getrennte Schichten führen, in denen Datenübertragungsobjekte (DTO) und Persistenzentitäten (Entity) nicht vermischt werden; die Umwandlung soll ausschließlich in der `*WebServiceBL`-Schicht erfolgen.
Ergebnis: Persistenzentitäten verlassen den Server nicht; die Oberfläche arbeitet ausschließlich mit DTOs bzw. ViewModels.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/ (464 Dateien, `*WebServiceBL`-Klassen als eigene Schicht) - Begründung: Die physische Trennung der Wandlungsschicht belegt die Architekturregel.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptWebServiceBL.cs (239 KB) gegenüber src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (609 KB) - Begründung: Konkretes Paar aus Wandlungs- und Fachlogikschicht derselben Domäne.
- [KONTEXT] docs/getting-started/general-structure.md:5-13 (Schichtentabelle) - Begründung: Beschreibt die Schichten und den je Schicht verwendeten Objekttyp.
- [KONTEXT] docs/reference/architecture/dtos-and-entities.md - Begründung: Erläutert die Trennung von DTO und Entity.
Prüfidee: Kein `CentronRestService`-Rückgabetyp verweist auf einen Typ aus dem Namensraum `Centron.Data.Entities`.
Tracelinks: SyRS-032, SyRS-033; StRS-001
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-002
Titel: Datenmodell der Zugriffsberechtigungen
Ebene: SwRS
Typ: Daten
Akteur: Datenbank / Komponente `AppRightsBL`
Vorbedingung: –
Fakt: Das Rechtemodell besteht aus vier Tabellen mit deutschen Legacy-Namen: `Sichrech` (Rechte, Entität `AppRight` mit `I3D`, `Text`, `Parent`), `Sichgrup` (Gruppen, Entität `AppGroup` mit `I3D`, `Name`, `BranchI3D`, `Status`), `Sichtrus` (Gruppe↔Recht, Entität `AppGroupRightAssignment` mit `GroupI3D`, `RightI3D`) und `Sichmemb` (Benutzer↔Gruppe, Entität `AppUserMember` mit `AppUserI3D`, `GroupI3D`); Benutzer liegen in `Sichbenu` (Entität `AppUser`). Rechte sind hierarchisch (`AppRight.Parent`); beim Zuweisen eines Rechts wird rekursiv auch das übergeordnete Recht zugewiesen (`SaveAndAssignGroupToRight` ruft sich für `selectedRight.Parent` selbst auf). Beim Löschen einer Gruppe werden verwaiste Zuordnungen bereinigt (`DELETE FROM Sichtrus WHERE Gruppe NOT IN (SELECT I3D FROM Sichgrup)`).
Aussage: Das System soll Rechte als hierarchische Struktur führen, Gruppen filialbezogen zuordnen können und bei der Zuweisung eines Rechts automatisch dessen übergeordnete Rechte mitzuweisen, damit Menüzweige erreichbar bleiben.
Ergebnis: Nach Zuweisung eines Unterrechts besitzt die Gruppe auch alle darüberliegenden Rechte; nach Löschung einer Gruppe existieren keine verwaisten Zuordnungen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:261-278 (`SaveAndAssignGroupToRight` mit rekursivem `Parent`-Aufruf) - Begründung: Belegt die Hierarchie als aktive Regel, nicht nur als Datenstruktur.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:578-590 (`ResetDefaultRightGroups` mit Bereinigungs-SQL) - Begründung: Belegt Tabellennamen und Referenzbereinigung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:39-48 (`AppGroup.BranchI3D`) - Begründung: Belegt die Filialzuordnung von Gruppen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:565-573 (SQL-Kommentar zur Erzeugung der Standardrechtestruktur aus `Sichgrup`/`Sichtrus`) - Begründung: Nennt die Tabellen und Spalten explizit.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Rights/DefaultRightsStructure.txt (eingebettete Ressource) - Begründung: Auslieferungsstand der Standardrechtegruppen.
Prüfidee: Nach Zuweisung eines Blattrechts an eine leere Gruppe enthält `Sichtrus` auch die Einträge aller übergeordneten Rechte des Pfads.
Tracelinks: SyRS-009, SyRS-014; StRS-002
Konsolidierung: nein
Status: belegt; Workaround (Deutsche Legacy-Tabellennamen `Sichrech`/`Sichgrup`/`Sichtrus`/`Sichmemb`/`Sichbenu` weichen von der geltenden Namenskonvention ab und sind aus Kompatibilitätsgründen unverändert.)
```
```
ID: SwRS-003
Titel: Wiederherstellbare Standardrechtestruktur
Ebene: SwRS
Typ: funktional
Akteur: Komponente `AppRightsBL`
Vorbedingung: Ein Benutzer löst das Zurücksetzen der Standardrechtegruppen aus.
Fakt: `AppRightsBL.ResetDefaultRightGroups` liest die eingebettete Ressource `Centron.BusinessLogic.Administration.Rights.DefaultRightsStructure.txt` (Format: Gruppenname, Tabulator, kommaseparierte Recht-IDs), löscht in einer Transaktion alle Gruppen mit diesen Namen, bereinigt verwaiste Zuordnungen in `Sichtrus` und `Sichmemb` und legt die Gruppen mit ihren Rechten neu an. Die Gruppen „Administratoren" und „RMM Systemuser Group" sind laut Kommentar von der Erzeugung der Ressourcendatei ausgenommen.
Aussage: Das System soll eine ausgelieferte Standardrechtestruktur bereitstellen und wiederherstellbar machen, ohne dabei die Administratorgruppe oder Systemgruppen zu verändern.
Ergebnis: Nach dem Zurücksetzen existieren alle in der Ressourcendatei genannten Gruppen mit exakt den dort hinterlegten Rechten; benutzerdefinierte Gruppen und die Administratorgruppe bleiben unverändert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:563-640 (`ResetDefaultRightGroups`, `GetDefaultRightsStructure`, `GetDefaultRightsStructureFileContent`) - Begründung: Vollständiger Mechanismus einschließlich Transaktionsklammer und Ressourcenzugriff.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:565-573 (SQL-Kommentar mit Ausschluss von „Administratoren" und „RMM Systemuser Group") - Begründung: Belegt den Ausschluss der Systemgruppen.
Prüfidee: Nach dem Zurücksetzen entspricht die Rechtezuordnung jeder Standardgruppe zeichengenau der Ressourcendatei; eine zuvor angelegte eigene Gruppe existiert unverändert weiter.
Tracelinks: SyRS-012, SyRS-013, SyRS-014; StRS-002
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-004
Titel: Objektartschlüssel als systemweiter Verweismechanismus
Ebene: SwRS
Typ: Daten
Akteur: Gesamtsystem
Vorbedingung: Ein Datensatz verweist auf ein Objekt unbekannten Typs.
Fakt: `CentronObjectKindNumeric` definiert 205 Objektarten mit stabilen numerischen Werten. Der Kopfkommentar schreibt vor: „Neue Arten MÜSSEN am Ende eingefügt werden, ansonsten kriegen die Leute bei dem Web-Service ein Problem"; neue .NET-Konstanten beginnen ab 7600000, die nächste freie ist 7600154 laut Fußkommentar. Polymorphe Verweise werden systemweit als Paar `ObjectI3D` + `ObjectKind` geführt; in Legacy-Tabellen entspricht dem das Paar `AnlageI3D` + `AnlageArt`. Der Änderungsprotokoll-Datensatz `ChangeLog` verwendet dasselbe Paar.
Aussage: Das System soll Verweise auf Objekte unterschiedlicher Art einheitlich über das Paar aus numerischer Objektart und Objekt-ID abbilden; die numerischen Werte sollen unveränderlich sein.
Ergebnis: Ein Protokoll-, Dokument- oder Verweisdatensatz kann ohne typspezifische Tabelle auf jedes Geschäftsobjekt zeigen; bestehende Werte bleiben über Versionsgrenzen hinweg stabil.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:6-12 (Warnkommentar zur Stabilität der Werte), :263 (nächste freie Konstante) - Begründung: Explizite, im Code festgehaltene Kompatibilitätsregel.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:127-137 (`ObjectI3D`, `ObjectKind`) - Begründung: Konkrete Anwendung des Verweismusters.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs:266-317 (`IsReceipt`, `IsCustomerReceipt`, `IsSupplierReceipt`, `GetAssetName`) - Begründung: Belegt die fachliche Gruppierung der Objektarten im Code.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:129-143 (`AnlageI3D` + `AnlageArt`, Wertetabelle 1..6, 22) - Begründung: Ordnet die Legacy-Entsprechung zu und bestätigt die Wertegleichheit.
Prüfidee: Für jede Objektart, auf die ein `ChangeLog`-Eintrag verweisen kann, existiert genau ein Wert in `CentronObjectKindNumeric`; kein bestehender Wert wurde zwischen zwei Releases geändert.
Tracelinks: SyRS-016; StRS-003, StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-005
Titel: Lizenzkomponente als Singleton mit einmaliger Initialisierung
Ebene: SwRS
Typ: funktional
Akteur: Komponente `LicenseManager`
Vorbedingung: Die Anwendung startet.
Fakt: `LicenseManager` ist ein Singleton mit `Initialize(LicensingManagerSettings)`; ein zweiter Aufruf wirft „The LicenseManager was already initialized. It can't be initialized multiple times."; ein Zugriff auf `Instance` vor der Initialisierung wirft „The LicenseManager is not initialized. Make sure to call the Initialize method at application startup.". Es existieren drei Konfigurationsvarianten: `SettingsForWebService()` (echter `OfficeClient`, Dateicache, Zusatzdaten Datenbank-ID/-Name/-Erstelldatum/-Eigentümer-SID, Maschinenname, Windows-Dienstname), `SettingsForCentronNet(Func<Task<string>>)` (`FakeOfficeClient`, `CheckIfLicenseIsValidForHardwareIDs = false`) und `SettingsForTests(Dictionary<Guid,string>)` (im Ablauf erzeugtes 1024-Bit-Schlüsselpaar, feste Hardware-ID `Dongle.12345678`). Im DEBUG-Build des Clients wird eine Sonderkonfiguration ohne `FakeOfficeClient` verwendet.
Aussage: Das System soll die Lizenzverwaltung als genau einmal initialisierte, prozessweite Komponente führen, deren Bezugsquelle je Ausführungsumgebung (Server, Client, Test) austauschbar ist.
Ergebnis: Client und Server verwenden dieselbe Lizenzlogik bei unterschiedlicher Bezugsquelle; Tests laufen ohne Lizenzserver.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:174-195 (Singleton-Erzwingung mit beiden Fehlermeldungen) - Begründung: Belegt die Einmaligkeitsregel unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:47-115 (`SettingsForWebService` inkl. Zusatzdaten für die Lizenzserver-Identifikation) - Begründung: Belegt, welche Systemmerkmale zur Lizenzbindung übertragen werden.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs:140-173 (`SettingsForTests`) - Begründung: Belegt die Testbarkeit ohne externen Dienst.
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/FakeOfficeClient.cs - Begründung: Implementiert den Client-Bezugsweg über den Web-Service.
Prüfidee: Ein zweiter `Initialize`-Aufruf im selben Prozess führt zur genannten Ausnahme; ein Test mit `SettingsForTests` läuft ohne Netzwerkzugriff.
Tracelinks: SyRS-007, SyRS-008, SyRS-015; StRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-006
Titel: Vererbungsstruktur der Belegentitäten
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: –
Fakt: `ReceiptBase : BaseEntity, IReceiptBase` definiert die für alle Belegarten gemeinsamen Merkmale: Belegkopf (`Number`, `Date`, `Version`, `State`, `EditorI3D`, `DirectoryI3D`), Filiale (`BranchI3D`, `BranchOrigin`), Währung (`CurrencyI3D`, `CurrencyFactor`, `CurrencyString`, `ExclusiveOfVAT`), Kontakt (`Receiver`, `Phone`, `Fax`, `Email`), Anschrift (`AddressI3D`, `ContactPersonI3D`, `Street`, `HasPostOfficeBox`, `PostOfficeBox`, `Zip`, `City`, `ContactName`, `CountryI3D`), Prüfspur (`CreatedByI3D`, `CreatedAt`, `CreatedThroughApplicationVersion`, `ChangedByI3D`, `ChangedAt`, `ChangedThroughApplicationVersion`, `ChangedThroughApplication`), Systemfelder (`ConcurrencyControlGuid`, `CustomUpdateArticlePricesAndTexts`) sowie vier Empfängerrollen (`ReceiptReceiver`, `ReceiptReceiverInvoice`, `ReceiptReceiverDelivery`, `ReceiptReceiverLicense`). Abstrakt bleiben `ReceiptKind` und die vier Positionsoperationen `GetReceiptItems`, `SetReceiptItems`, `AddItem`, `RemoveItem`. Ergänzende Merkmale werden über Kennzeichnungsschnittstellen zugeschaltet: `IReceiptWithIsCash`, `IReceiptWithPaymentCondition`, `IReceiptWithEsr`, `IReceiptWithContingent`, `IReceiptClosedThroughRMA`, `IReceiptWithCustomStringProperty1`, `IReceiptItemWithOrigin`, `IReceiptItemWithBarcodes`, `IReceiptItemWithOnlyPriceValue`, `ICustomerReceiptBase`, `ISupplierReceiptBase`.
Aussage: Das System soll gemeinsame Belegmerkmale in einer abstrakten Basisklasse führen und belegartspezifische Merkmale über Kennzeichnungsschnittstellen zuschalten, sodass die gemeinsame Verarbeitungslogik typunabhängig arbeiten kann.
Ergebnis: Neue Belegarten erfordern keine Änderung der gemeinsamen Verarbeitungslogik, sondern nur die Implementierung der Basisklasse und der zutreffenden Kennzeichnungsschnittstellen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs:9-72 - Begründung: Vollständige Basisdefinition mit allen gemeinsamen Feldern und abstrakten Mitgliedern.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3764, 3816, 3823, 3549 (Typprüfungen `receipt is IReceiptWithIsCash`, `IReceiptClosedThroughRMA`, `IReceiptWithEsr`, `IReceiptContract`) - Begründung: Belegt, dass die Verarbeitungslogik über Kennzeichnungsschnittstellen verzweigt.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:13-55 - Begründung: Ordnet den Belegarten Entitätsklassen und Ablageorte zu.
Prüfidee: Alle sieben Kundenbeleg- und fünf Lieferantenbelegentitäten erben von `ReceiptBase` und implementieren `ReceiptKind` mit dem passenden Wert aus `CentronObjectKindNumeric`.
Tracelinks: SyRS-016, SyRS-017, SyRS-019, SyRS-020, SyRS-022, SyRS-023, SyRS-024; StRS-005
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-007
Titel: Zweigleisige Belegpersistenz über Legacy-Tabellen und moderne Sichten
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: Ein Beleg wird geladen oder gespeichert.
Fakt: Für jede Belegart existieren nebeneinander (a) die deutschsprachige Legacy-Tabelle (`AngKopf`/`AngPos`, `AufKopf`/`AufPos`, `LiefKopf`/`LiefPos`, `RechKopf`/`RechPos`, `VertragKopf`/`VertragPos`, `GutKopf`/`GutPos`, `AbholKopf`/`AbholPos`), (b) eine englischsprachige Sicht (`Offers`/`OfferItems`, `Orders`/`OrderItems`, …) und (c) Versionstabellen (`*KopfVersions`/`*PosVersions`) mit zugehörigen Sichten. Das **Lesen** erfolgt über die modernen Entitäten und Sichten. Das **Schreiben** erfolgt über eigene `SaveReceipt*Repository`-Klassen, die die modernen Entitäten in temporäre Legacy-Entitäten (`Centron.Entities/Entities/DbEntities/`, 39 Dateien; Mappings unter `Centron.DAO/Mappings/TemporaryEntities/`) übertragen: Kopffelder in `SynchronizeReceiptData`, Positionsfelder in `SynchronizeReceiptItemData`. Ein neues Feld muss laut Projektdokumentation an zehn Stellen nachgezogen werden.
Aussage: Das System soll den Lese- und den Schreibpfad der Belegpersistenz konsistent halten; ein persistiertes Belegfeld muss auf beiden Pfaden vollständig abgebildet sein.
Ergebnis: Ein neu eingeführtes Belegfeld ist nach Speichern und erneutem Laden unverändert vorhanden; die Versionstabelle enthält dieselbe Spalte.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/DbEntities/ (39 temporäre Legacy-Entitäten) und src/backend/Centron.DAO/Mappings/TemporaryEntities/ - Begründung: Belegt die Existenz des zweiten, legacy-orientierten Schreibpfads im Code.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:174-190 (Zehn-Punkte-Checkliste, „Critical Save Warning") - Begründung: Beschreibt die Konsistenzpflicht und die konkrete Fehlerwirkung („the value may load correctly from the view but will not be persisted on save").
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:249-255 (Beschreibung der `SaveReceipt*Repository`-Klassen) - Begründung: Nennt die Methodennamen des Schreibpfads.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:104-181 (Spaltenliste `VertragKopf`/`VertragPos`, Versionierungs-SQL) - Begründung: Konkretisiert die Legacy-Struktur für die Belegart Vertrag.
Prüfidee: Ein Ende-zu-Ende-Test, der ein neues Belegfeld setzt, speichert, neu lädt und zusätzlich den Rohwert in der Legacy-Tabelle prüft, schlägt fehl, wenn nur die moderne Zuordnung ergänzt wurde.
Tracelinks: SyRS-017, SyRS-018; StRS-005, StRS-014
Konsolidierung: Kandidat: Legacy-Tabelle, moderne Sicht, temporäre Legacy-Entität und Repository bilden dieselbe fachliche Struktur viermal ab; im Zielsystem zwingend auf ein Modell zu reduzieren.
Status: belegt; Workaround (Der doppelte Persistenzpfad ist ein historisch bedingter Kompatibilitätsmechanismus zur Delphi-Vorgängeranwendung und die aufwendigste Einzelstruktur der Belegverarbeitung.)
```
```
ID: SwRS-008
Titel: Versionstabellen als strukturgleiche Kopien
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: Eine neue Belegversion wird gespeichert.
Fakt: Zu jeder Belegtabelle existiert eine Versionstabelle mit identischer Spaltenmenge, ergänzt um `OriginalI3D` (Verweis auf den Ursprungsdatensatz) und – bei Positions-Versionstabellen – `KopfVersionsI3D` (Verweis auf die Kopfversion); die Spalten `I3D` und `OriginalI3D` der Quelltabelle werden nicht übernommen. Das Kopieren erfolgt mit einem dynamisch erzeugten Feldliste-INSERT (`DoGetFieldList()`, Muster `INSERT INTO AngKopfVersions (…) SELECT …, I3D AS OriginalI3D FROM AngKopf WHERE I3D = @receiptId`).
Aussage: Das System soll Belegversionen als vollständige Momentaufnahmen in strukturgleichen Versionstabellen ablegen; jede Spalte der Quelltabelle muss in der Versionstabelle mit identischem Datentyp vorhanden sein.
Ergebnis: Eine Belegversion ist vollständig rekonstruierbar; ein fehlendes Feld in der Versionstabelle führt zu einem Laufzeitfehler beim Versionieren, nicht zu stillem Datenverlust.
Belege:
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:147-204 („Version tables … are exact 1:1 copies", INSERT-Muster, „⚠️ Critical Warning") - Begründung: Beschreibt Struktur, Erzeugungsmechanismus und Fehlerwirkung vollständig.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:150-181 - Begründung: Wiederholt die Regel für Verträge mit konkretem SQL.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3629 (`SaveReceiptVersion(receipt, previousReceiptVersion)`) - Begründung: Belegt den Aufrufpunkt im Speicherpfad.
Prüfidee: Ein Vergleich der Spaltenmengen von `AngKopf` und `AngKopfVersions` ergibt Gleichheit bis auf `I3D`/`OriginalI3D`; dasselbe gilt für alle sieben Belegarten.
Tracelinks: SyRS-017; StRS-014
Konsolidierung: nein
Status: belegt; Workaround (Die Konsistenz wird nicht durch ein Datenbank-Constraint, sondern durch Entwicklerdisziplin und einen Laufzeitfehler gesichert. Der `PRIMÄR`-Beleg für die Kopiermechanik selbst – `AssetHeadDAO.SaveAssetVersion` – wurde in dieser Iteration nicht im Detail gelesen; die Struktur stützt sich auf Projektdokumentation und den Aufrufpunkt im Speicherpfad.)
```
```
ID: SwRS-009
Titel: Delegation belegartspezifischer Logik über ein Strategiemuster
Ebene: SwRS
Typ: funktional
Akteur: Komponente `ReceiptBL`
Vorbedingung: Eine belegartabhängige Entscheidung ist zu treffen.
Fakt: `ReceiptBL` verwendet durchgängig `this._specificLogics.Execute(receipt, f => f.<Operation>(…))` bzw. `Execute<TResult, TReceipt>(…)`, um an eine belegartspezifische Implementierung von `IReceiptSpecificLogic` zu delegieren. Es existieren mindestens 13 Implementierungen: `OfferSpecificLogic`, `OrderSpecificLogic`, `DeliveryListSpecificLogic`, `InvoiceSpecificLogic`, `PickupListSpecificLogic`, `CreditVoucherSpecificLogic`, `ContractSpecificLogic` sowie die Lieferantenvarianten `SupplierOrderSpecificLogic`, `SupplierInvoiceSpecificLogic`, `SupplierDeliveryListSpecificLogic`, `SupplierCreditVoucherSpecificLogic`. Delegierte Entscheidungen sind u. a.: `GetNumberGroup`, `HasRightToCreateANewReceipt`, `HasRightToCreateANewReceiptOnlyOwnBranch`, `HasRightToEditReceipt`, `HasRightToEditReceiptOnlyOwnBranch`, `HasRightToViewReceipt`, `BlockNewReceiptsDunningLevel`, `TakesPlaceInLimitCalculation`, `GetUsedLimitAmount`, `UpdatesStock`, `IncrementsStock`, `UpdatesIntake`, `CreatesAccountActivities`, `WarnIfUserMakesNegativeArticleBooking`, `UserNeedsRightToMakeNegativeArticleBooking`, `TryLockReceipt`, `UnLockReceipt`, `SaveReceipt`, `SaveReceiptVersion`, `BeforeReceiptIsSaved`, `AfterReceiptIsSaved`, `OnReceiptNewVersion`, `GetParentDirectoryForReceipts`, `GetNewVersionUpdateDateSetting`, `GetNewVersionUpdateEditorSetting`, `FillReportGroupParameters`.
Aussage: Das System soll alle belegartabhängigen Entscheidungen über eine gemeinsame Schnittstelle mit je einer Implementierung pro Belegart auflösen, sodass die gemeinsame Belegverarbeitung frei von Fallunterscheidungen nach Belegart bleibt.
Ergebnis: Das Hinzufügen einer neuen Belegart erfordert eine neue `IReceiptSpecificLogic`-Implementierung, aber keine Änderung an `ReceiptBL`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs (25 KB) - Begründung: Definiert den vollständigen Vertrag der belegartspezifischen Entscheidungen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/{Offers,Orders,DeliveryLists,Invoices,PickupLists,CreditVouchers,ContractLists,Supplier*}/…SpecificLogic.cs (13 Implementierungen, 23–46 KB) - Begründung: Belegt die vollständige Umsetzung je Belegart.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3841, 3846, 3854-3857, 10201, 10277, 10284, 10304 (Delegationsaufrufe) - Begründung: Belegt die durchgängige Verwendung des Musters an sicherheits- und persistenzrelevanten Stellen.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md:230-235 („SpecificLogics Pattern") - Begründung: Benennt das Muster.
Prüfidee: Eine Textsuche nach `switch (receipt.ReceiptKind)` in `ReceiptBL.cs` liefert keine fachlichen Fallunterscheidungen; alle Verzweigungen laufen über `_specificLogics`.
Tracelinks: SyRS-017, SyRS-018, SyRS-021, SyRS-023, SyRS-025, SyRS-029; StRS-005, StRS-006, StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-010
Titel: Reflexionsbasierte Auflösung generischer Belegoperationen
Ebene: SwRS
Typ: funktional
Akteur: Komponente `ReceiptBL`
Vorbedingung: Eine Belegoperation wird ohne statisch bekannten Belegtyp aufgerufen.
Fakt: `ReceiptBL.SaveReceipt(IReceiptBase receipt, …)` und `ReceiptBL.CreateNewVersion(CentronObjectKindNumeric receiptKind, …)` ermitteln zur Laufzeit die generische Überladung über Reflexion (`this.GetType().GetMethods().First(f => f.Name == nameof(...) && f.IsGenericMethod).MakeGenericMethod(...)`) und rufen sie per `Invoke` auf. Die Typparameter werden aus `receipt.GetType()` und `receipt.ReceiptKind.GetReceiptItemType()` bzw. `receiptKind.GetReceiptType()` abgeleitet.
Aussage: [HYPOTHESE] Das System soll generische Belegoperationen ohne Reflexion auflösen, da Reflexion Typfehler erst zur Laufzeit sichtbar macht und die Ausführungsgeschwindigkeit beeinträchtigt.
Ergebnis: Belegoperationen sind zur Übersetzungszeit typgeprüft.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3517-3521 (`SaveReceipt`, Reflexionsauflösung) - Begründung: Belegt das Muster im zentralen Speicherpfad.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3063-3067 (`CreateNewVersion`, dasselbe Muster) - Begründung: Belegt die Wiederholung des Musters.
Prüfidee: Ein Aufruf von `SaveReceipt` mit einem Belegtyp ohne passende Positionsklasse führt zu einer Laufzeitausnahme statt zu einem Übersetzungsfehler.
Tracelinks: SyRS-017; StRS-005
Konsolidierung: nein
Status: HYPOTHESE
Fehlende Information: Ob die Reflexionsauflösung bewusst gewählt wurde (z. B. wegen der nicht-generischen Legacy-Schnittstellensignatur) oder eine ablösbare Altlast ist, geht aus den Artefakten nicht hervor. Es fehlt ein Kommentar oder eine Entwurfsnotiz; ohne diese Information ist die Zielarchitekturentscheidung nicht belegbar. Zur Klärung durch Fachexperten vorgemerkt.
```
---
## 2. Fachkomponenten
```
ID: SwRS-011
Titel: Komponentenschnitt der Ticketverarbeitung
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Helpdesk
Vorbedingung: –
Fakt: Der Ordner `src/backend/Centron.BL/Sales/Support/` enthält 53 Klassen mit klarer Aufgabenteilung: `HelpdeskBL` (Kernlogik, Speichern, Rechteprüfung), `HelpdeskSettingsBL` (87 KB, Zustände und Konfiguration), `EscalationBL` (69 KB, Eskalationen), `HelpdeskHistoryBL` (Verlauf), `HelpdeskCustomerBL`, `HelpdeskReplacementBL` (Variablenersetzung), `HelpdeskTimerBL`, `HelpdeskTimeRecordingBL`, `HelpdeskTimerArticleBookingBL`, `HelpdeskTimerLogBL`, `HelpdeskSearchBL`, `HelpdeskOverviewFilterBL`, `HelpdeskCloseBL`, `HelpdeskForwardBL`, `HelpdeskPatternBL`, `HelpdeskMailBL`, `HelpdeskSendMailBL`, `UpdateHelpdeskBL`, `HelpdeskConnectionNumberBL`, `AdressstammReplacementBL`.
Aussage: Das System soll die Ticketverarbeitung in fachlich abgegrenzte Komponenten für Kernlogik, Konfiguration, Zeiten, Eskalation, Suche, Weiterleitung, Vorlagen, Abschluss und Benachrichtigung gliedern.
Ergebnis: Eine Änderung an der Eskalationslogik berührt weder die Zeiterfassung noch die Suchlogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/ (53 Klassen mit den genannten Namen und Größen) - Begründung: Der Komponentenschnitt ist unmittelbar aus der Dateistruktur ablesbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`new HelpdeskSettingsBL(this.Session).GetClosedHelpdeskState()`) - Begründung: Belegt die Auslagerung der Zustandskonfiguration in eine eigene Komponente.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/EscalationsService.cs, ValidateHelpdeskFingerprintService.cs - Begründung: Belegt die zeitgesteuerten Anteile der Ticketverarbeitung.
Prüfidee: Die Ticketzustände sind ausschließlich über `HelpdeskSettingsBL` erreichbar; `HelpdeskBL` enthält keine hartcodierten Zustands-IDs.
Tracelinks: SyRS-026, SyRS-027; StRS-007
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-012
Titel: Konfigurierbare Ticketzustände statt fester Zustandsaufzählung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `HelpdeskSettingsBL`
Vorbedingung: –
Fakt: Im Gegensatz zum Belegzustand (`ReceiptState`, drei feste Werte) existiert für Tickets **keine** Zustandsaufzählung im Code. Der Abschlusszustand wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` aus der Konfiguration ermittelt und mit `entity.HelpdeskState` verglichen. Ticketarten, Haupt- und Unterkategorien sind ebenfalls Stammdaten (`HelpdeskType`, `MainCategory`, `SubCategory1`, `SubCategory2`) mit eigenen Anlagerechten (`ADD_NEW_HELPDESK_TYPE`, `ADD_NEW_HELPDESK_MAIN_CATEGORY`, `ADD_NEW_HELPDESK_SUB_CATEGORY1`, `ADD_NEW_HELPDESK_SUB_CATEGORY2`). Für Web-Anfragen existiert separat die feste Aufzählung `RequestStateEnum` mit `Requested = 0` („Angefragt"), `Veryfied = 1` („Verifiziert"), `Accepted = 2` („Angenommen"), `Denied = 3` („Abgelehnt").
Aussage: Das System soll Ticketzustände, -arten und -kategorien als anwenderpflegbare Stammdaten führen und den Abschlusszustand über eine Konfiguration bestimmen; Zustandsprüfungen im Code sollen ausschließlich gegen diese Konfiguration erfolgen.
Ergebnis: Ein Anwender kann eigene Ticketzustände anlegen; der Abschlussmechanismus arbeitet ohne Codeänderung mit dem konfigurierten Abschlusszustand.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433 (`GetClosedHelpdeskState()`) - Begründung: Belegt die Konfigurationsabhängigkeit des Abschlusszustands unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:367-374 (Variablenersetzung mit `@@Hauptkategorie@@`, `@@Unterkategorie1@@`, `@@Unterkategorie2@@`, `@@Typ@@`, `@@Ansprechpartner@@`) - Begründung: Belegt Kategorien und Typ als Stammdatenobjekte mit Namensattribut.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/Entities/Sales/Customers/Enum/RequestStateEnum.cs - Begründung: Belegt die abweichende, feste Zustandsaufzählung für Web-Anfragen.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1963-1967 (Anlagerechte für Typ und Kategorien) - Begründung: Belegt die Pflegbarkeit als berechtigte Anwenderhandlung.
Prüfidee: Nach Anlage eines neuen Ticketzustands und dessen Festlegung als Abschlusszustand greift die Rechteprüfung `CLOSE_REQUEST` auf den neuen Zustand.
Tracelinks: SyRS-026; StRS-007, StRS-024
Konsolidierung: Kandidat: Zwei Zustandsmodelle nebeneinander (konfigurierbare Ticketzustände, feste `RequestStateEnum` für Web-Anfragen); im Zielsystem zu vereinheitlichen.
Status: belegt
```
```
ID: SwRS-013
Titel: Komponentenschnitt der Belegpreis- und Positionsverarbeitung
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Belege
Vorbedingung: –
Fakt: Die Positions- und Preisverarbeitung ist auf spezialisierte Komponenten unter `src/backend/Centron.BL/Sales/Receipts/Internal/` verteilt: `ReceiptItemPriceBL` (Preisberechnung, `ChangeBasePrice`), `ReceiptPriceHelperBL` (`CalculateReceiptPrices` mit `NetPrice`/`GrossPrice`, `CalculateReceiptItemPrices`), `ReceiptItemTimerBL` (Ticketzeiten, 104 KB), `ReceiptBarcodeBL` (Barcodes, 98 KB), `ReceiptArticleBookingBL` (Lagerbuchung, 50 KB), `ReceiptContractHelperBL` (Kontingente, 62 KB), `ReceiptProvisionBL` (Provision, 45 KB), `ReceiptAddressAndContactPersonHelperBL` (55 KB), `ReceiptItemSalutationAndAgreementReplacementBL` (26 KB), `ReceiptReceiverUpdaterBL`, `ReceiptItemAccountBL`, `ReceiptEsrBL` (Schweizer Einzahlungsschein), `ReceiptLayoutItemKindPdfHelperBL`. Ergänzend auf gleicher Ebene: `ReceiptItemBL` (225 KB), `ReceiptLogBL` (74 KB), `ReceiptProgressionBL`, `ReceiptCartBL`, `ReceiptCartReleaseSystemBL`, `DownPaymentBL` (Anzahlungen), `ReceiptTemplateBL`.
Aussage: Das System soll Preisberechnung, Positionsverwaltung, Barcodeverwaltung, Lagerbuchung, Kontingentverrechnung, Provisionsermittlung und Anschriftenpflege in eigenständigen Komponenten kapseln, die von der Belegkernlogik aufgerufen werden.
Ergebnis: Eine Änderung der Preisberechnung erfordert keine Änderung der Belegkernlogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ (14 Komponenten mit den genannten Namen und Größen) - Begründung: Komponentenschnitt unmittelbar aus der Dateistruktur ablesbar.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:8699-8702 (`_receiptPriceHelperBL.CalculateReceiptPrices(receipt).NetPrice / .GrossPrice`) - Begründung: Belegt die Delegation der Preisberechnung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:9075 (`_receiptItemPriceBL.ChangeBasePrice(item, minPrice)`) - Begründung: Belegt die Delegation der Preisänderung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7250-7252 (`FillReceiptWithProvision`, `FillReceiptWithBarcodes`, `FillReceiptWithTimerI3Ds`) - Begründung: Belegt die Delegation beim Laden ergänzender Belegdaten.
Prüfidee: `ReceiptBL.cs` enthält keine eigene Preisformel; alle Preisberechnungen laufen über `ReceiptPriceHelperBL` bzw. `ReceiptItemPriceBL`.
Tracelinks: SyRS-017, SyRS-021, SyRS-025; StRS-005, StRS-008, StRS-015, StRS-016
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-014
Titel: Verteilung der Vertragsabrechnung auf drei Komponenten
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Vertragsabrechnung
Vorbedingung: –
Fakt: Die Vertragsabrechnung ist auf drei Ebenen verteilt: `AutomaticFacturaBL.Contracts` (124 KB, Ermittlung fälliger Verträge und Abrechnungsparameter), `AutomaticFacturaWebServiceBL` (126 KB, Rechnungserzeugung `CreateInvoiceToContractComplete`, Zählerdaten, Staffelpreise, RMM-Positionen) und `ReceiptContractBL` (46 KB, Kontingentverrechnung, Geräte-/Zählerverwaltung, Stammblattzuordnung) sowie `ContractSpecificLogic` (46 KB). Die Rechnungserzeugung selbst delegiert an `ReceiptWebServiceBL.ForwardReceipt(...)`. Die Ablaufmessung erfolgt über `PerformanceTracer.StartTrace()` mit `PostTrace`-Marken.
Aussage: Das System soll die Vertragsabrechnung in Fälligkeitsermittlung, Rechnungserzeugung und vertragsspezifische Nachverarbeitung gliedern und die Rechnungserzeugung über den regulären Belegweiterverarbeitungspfad ausführen.
Ergebnis: Eine aus einem Vertrag erzeugte Rechnung durchläuft dieselben Validierungen wie eine manuell erfasste Rechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1815-1841 (`receiptBL.ForwardReceipt(...)` mit `originReceipts`) - Begründung: Belegt die Nutzung des regulären Weiterverarbeitungspfads.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs (124 KB) - Begründung: Belegt die eigenständige Fälligkeitsermittlung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ContractLists/ReceiptContractBL.cs (46 KB) - Begründung: Belegt die vertragsspezifische Nachverarbeitung.
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaWebServiceBL.cs:1702-1704 (`PerformanceTracer.StartTrace()`) - Begründung: Belegt eine eingebaute Laufzeitmessung dieses Vorgangs.
- [KONTEXT] docs/reference/receipts/contracts-backend.md:275-283 - Begründung: Beschreibt die Aufgabenteilung.
Prüfidee: Eine per Vertragsabrechnung erzeugte Rechnung erhält eine Nummer aus dem Rechnungsnummernkreis und durchläuft die Kreditlimitprüfung.
Tracelinks: SyRS-018, SyRS-029; StRS-006, StRS-021
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-015
Titel: Kapselung der elektronischen Rechnungserzeugung
Ebene: SwRS
Typ: Schnittstelle
Akteur: Komponente `InvoiceZugferdBL`
Vorbedingung: –
Fakt: `InvoiceZugferdBL` ist eine partielle Klasse (120 KB) mit den öffentlichen Einstiegspunkten `GetZugferFormat`, `GetZugferdFileName`, `GenerateZugferdFile`, `CreateZugferdConformPdfDocument` und dem internen Bereich „ZUGFeRD file generator". Die PDF-Erzeugung nutzt `DevExpress`-Klassen (`PdfDocumentProcessor`, `PdfZugferdVersion`, `PdfZugferdConformanceLevel`, `AttachZugferdInvoice`). Die Formatermittlung wird über `Session.Advanced.Cache.GetOrAdd($"GetZugferdFormatInternal{exportZUGFeRD}", …)` zwischengespeichert. Für österreichische E-Rechnung existiert separat `Centron.Api.EbInterface`, für den Import `ZugferdImportController` und `Centron.Gateway/ZUGFeRD21_Extended`.
Aussage: Das System soll die Erzeugung und den Import elektronischer Rechnungen in eigenen Komponenten kapseln, die Formatentscheidung zwischenspeichern und länderspezifische Formate über getrennte Bibliotheken bedienen.
Ergebnis: Eine neue Normversion erfordert eine Erweiterung von `ZugferdKind` und der Zuordnungstabellen, nicht aber Änderungen an der Belegverarbeitung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:52, 85-238 - Begründung: Belegt Kapselung, Einstiegspunkte und Zwischenspeicherung.
- [PRIMÄR] src/apis/Centron.Api.EbInterface/ - Begründung: Belegt die getrennte Bibliothek für das österreichische Format.
- [PRIMÄR] src/webservice/Centron.Controllers/Controllers/v1/Receipts/ZugferdImportController.cs, src/backend/Centron.Gateway/ZUGFeRD21_Extended/ - Begründung: Belegt den getrennten Importpfad.
- [KONTEXT] docs/guides/development/xrechnung.md:6-9 („Would be nice to switch to this in the future instead of creating our own implementation.") - Begründung: Dokumentiert die Eigenimplementierung und die erwogene Ablösung durch eine Fremdbibliothek.
Prüfidee: Ein Import einer ZUGFeRD-Rechnung über `ZugferdImportController` erzeugt einen Lieferantenbeleg; die Erzeugung einer Ausgangsrechnung nutzt ausschließlich `InvoiceZugferdBL`.
Tracelinks: SyRS-030; StRS-012
Konsolidierung: nein
Status: belegt; Workaround (Die ZUGFeRD-Erzeugung ist eine Eigenimplementierung; die Projektdokumentation benennt den Wechsel auf eine etablierte Open-Source-Bibliothek als wünschenswert.)
```
```
ID: SwRS-016
Titel: Anonymisierungskomponente mit Löschprotokoll
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `DataSecurityBL`
Vorbedingung: –
Fakt: `DataSecurityBL` (85 KB) implementiert für mindestens drei Datenmodelle getrennte Anonymisierungsroutinen: Kunden-Ansprechpartner (deutsche Legacy-Felder `Fon`, `Fax`, `KdEmail`, `Kommentar`, `Strasse`, `Plz`, `Ort`), Accounts-Ansprechpartner (englische Felder `Name`, `Matchcode`, `Phone`, `Fax`, `Email`, `Comment`, `Department`, `GeoInfoLatitude`, `GeoInfoLongitude`) und weitere. Die zugehörigen SQL-Anweisungen sind im Quelltext als auskommentierte Referenz enthalten (Zeilen 863–1098). Jeder überschriebene Wert wird über `DoAppendDeleteProtocol(deleteProtocol, Feldbezeichnung, Altwert)` mit deutscher Feldbezeichnung („E-Mail 1", „Mailing an E-Mail 1", „Freies Feld 1", „Abteilung", „Bild", „Active Directory SID", „Webseite", „Kommentar") protokolliert. Zusätzlich existiert die Funktion „Datenbank bereinigen" mit eigenem Recht `ACCESS_CLEANUP_DATABASE` und dem Feature-Schalter `ModuleFeatures.IsDsgvoDatabaseCleanupAvailable`.
Aussage: Das System soll für jede personenbezogene Datenstruktur eine Anonymisierungsroutine bereitstellen, die vor jeder Überschreibung den bisherigen Wert unter einer anwenderverständlichen Feldbezeichnung protokolliert.
Ergebnis: Das Löschprotokoll ist als Nachweis gegenüber der betroffenen Person und der Aufsichtsbehörde verwendbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1195-1275 (Protokollierung je Feld mit deutscher Bezeichnung) - Begründung: Belegt das Protokollmuster unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1598-1630 (zweite Anonymisierungsroutine für das Accounts-Modell) - Begründung: Belegt die Mehrfachimplementierung.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:36, 66 (`ACCESS_CLEANUP_DATABASE` und `ModuleFeatures.IsDsgvoDatabaseCleanupAvailable`) - Begründung: Belegt die doppelte Absicherung der Datenbankbereinigung.
Prüfidee: Das Löschprotokoll eines anonymisierten Ansprechpartners enthält für jedes zuvor belegte Feld genau eine Zeile mit Feldbezeichnung und Altwert.
Tracelinks: SyRS-028; StRS-013
Konsolidierung: Kandidat: Drei parallele Anonymisierungsroutinen für strukturell gleichartige Kontaktdaten; im Zielsystem als deklarative, feldattributgesteuerte Anonymisierung zusammenführbar.
Status: belegt
```
```
ID: SwRS-017
Titel: Attributgesteuerte Änderungsprotokollierung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `ChangeTrackingEventListener`
Vorbedingung: Eine Entität wird über NHibernate aktualisiert.
Fakt: Die Protokollierung ist ein `IPreUpdateEventListener`. Sie greift nur für Typen mit `[ChangeTrackingConfiguration(ObjectKind = …)]` und protokolliert nur Eigenschaften mit `[TrackChanges]`. Je geändertem Feld entsteht ein `ChangeLog` mit `ObjectI3D`, `ObjectKind`, `DisplayName` (`entity.ToString()`), `OldValue`, `NewValue`, `Property`, `Date`, `AppUser`; alle Textfelder werden auf 4000 Zeichen gekürzt (`Shorten(4000)`). Die Beschreibung folgt dem festen Muster „{Property} wurde von {OldValue} auf {NewValue} geändert.". Typ- und Attributauswertung werden in `ConcurrentDictionary` zwischengespeichert. Die Protokollierung unterbleibt mit Warnung, wenn (a) der Schlüssel kein `int` ist oder (b) `LoggedInUserManager.AppUserI3D` nicht gesetzt ist. Ausnahmen werden protokolliert, brechen die Aktualisierung aber nicht ab (`return false`, kein Veto).
Aussage: Das System soll Feldänderungen an gekennzeichneten Entitäten automatisch und unabhängig vom aufrufenden Anwendungsfall protokollieren; ein Fehler in der Protokollierung darf die fachliche Aktualisierung nicht verhindern.
Ergebnis: Jede Aktualisierung eines mit `[TrackChanges]` versehenen Feldes erzeugt einen Protokolleintrag mit Alt- und Neuwert, Zeitpunkt und Benutzer; fehlt der Benutzerkontext, wird der Vorgang mit Warnung übersprungen.
Belege:
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-99 (Ereignisbehandlung, Zwischenspeicherung, Ausnahmebehandlung ohne Veto) - Begründung: Vollständige Steuerlogik.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:112-142 (`CreateChangeLog`, Kürzung, Beschreibungsmuster, Voraussetzungen) - Begründung: Belegt Feldinhalte und Abbruchbedingungen.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:179-207 (`GetEntityData` mit Attributauswertung) - Begründung: Belegt die Attributsteuerung.
- [PRIMÄR] src/backend/Centron.DAO/ChangeTracking/LogHourlySurchargeRateChangesListener.cs - Begründung: Belegt einen zweiten, fachspezifischen Protokollierungs-Listener.
Prüfidee: Die Änderung eines `[TrackChanges]`-Feldes ohne gesetzten `LoggedInUserManager.AppUserI3D` erzeugt eine Warnung im Anwendungsprotokoll, aber keinen `ChangeLog`-Eintrag; die Änderung selbst wird gespeichert.
Tracelinks: SyRS-046; StRS-014
Konsolidierung: nein
Status: belegt; Workaround (Der Benutzerkontext wird über eine statische Klasse `LoggedInUserManager` übergeben; ist sie nicht gesetzt – etwa in Hintergrunddiensten –, entfällt die Protokollierung stillschweigend. Dies ist eine Lücke in der Revisionssicherheit.)
```
```
ID: SwRS-018
Titel: Datenmodell- und Namenskonventionen der Datenbank
Ebene: SwRS
Typ: Daten
Akteur: Datenbank
Vorbedingung: Eine Tabelle wird neu angelegt.
Fakt: Verbindliche Konventionen: alle Objekte im Schema `dbo` mit ausdrücklichem Präfix; Primärschlüssel stets `I3D` als `int IDENTITY(1,1) NOT NULL` mit gruppiertem Primärschlüsselindex; Fremdschlüsselspalten enden auf `I3D` mit dem Namen der referenzierten Tabelle als Präfix; Prüfspalten `CreatedByI3D`, `CreatedDate`, `ChangedByI3D`, `ChangedDate`; logisches Löschen über `IsDeleted`, `DeletedByI3D`, `DeletedDate`; Texte als `nvarchar` (nicht `varchar`); Datum/Zeit als `datetime2(2)` bzw. `datetime2(0)`; Wahrheitswerte als `bit`; Tabellennamen in PascalCase, Plural für Entitätssammlungen, Singular für Nachschlagetabellen; nicht gruppierte Indizes nach dem Muster `IX_Tabelle_Spalte1_Spalte2`. Bestehende deutsche Namen bleiben aus Kompatibilitätsgründen unverändert; neue Namen sind englisch. Die Konvention wird über `ScriptHelpers.AddTableIfNotExists` technisch unterstützt, das `I3D` und den Primärschlüssel automatisch erzeugt.
Aussage: Das System soll für alle neuen Datenbankobjekte eine einheitliche Namens-, Schlüssel- und Prüfspaltenkonvention anwenden und das logische Löschen dem physischen vorziehen.
Ergebnis: Jede neue Tabelle besitzt `I3D` als Identitätsprimärschlüssel, Prüfspalten und – sofern Datensätze gelöscht werden können – die Löschkennzeichnung.
Belege:
- [KONTEXT] docs/guides/database/database-conventions.md:5-99 - Begründung: Vollständige Konventionsdefinition mit Beispielen.
- [KONTEXT] docs/reference/database/script-rules.md:49-57 (automatische `I3D`-Erzeugung, Regeln für Prüfspalten, Ausnahme für unveränderliche Historientabellen) - Begründung: Beschreibt die technische Durchsetzung und die begründeten Ausnahmen.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/ScriptHelpers.cs - Begründung: Implementiert die Konvention in den Hilfsmethoden, die alle Skripte verwenden.
- [PRIMÄR] src/backend/Centron.Entities/Entities/ (1 179 Entitätsdateien) und src/backend/Centron.DAO/Mappings/ (983 Zuordnungsdateien) - Begründung: Umfang des nach diesen Konventionen abgebildeten Datenmodells.
Prüfidee: Eine Stichprobe von 20 in den letzten 50 Skripten angelegten Tabellen erfüllt alle genannten Konventionen.
Tracelinks: SyRS-039; StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-019
Titel: Rechteabhängige Rücksetzung von Preisänderungen
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `ReceiptBL`
Vorbedingung: Ein Beleg mit geänderten Einkaufs- oder Verkaufspreisen wird gespeichert.
Fakt: Im Speicherpfad wird `UpdateArticlePositionsPurchasePriceAndSellPriceIfUserDoesNotHaveRightToChangeThem(currentUser, receipt, previousReceiptVersion)` aufgerufen. Für jede Belegart existieren getrennte Rechte für Einkaufs- und Verkaufspreisänderung: `Offer.CHANGE_PURCHASE_PRICE = 20400233` / `CHANGE_PRICE = 20400285`, `Order` 20400234 / 20400286, `DeliveryList` 20400242 / 20400287, `PickUpList` – / 20400288, `Invoice` 20400091 / 20400289, `CreditVoucher` – / 20400290, `Contracts` – / 20400291; zusätzlich `Offer.CAN_CHANGE_PROJECT_PURCHASE_PRICE = 20400308`. Ferner wird `UpdateArticlePositionsPurchasePriceEqualsSellPrice`, `UpdateArticlePositionsNotDiscountable` und `UpdateOnlyPriceValue` aufgerufen.
Aussage: Das System soll Preisänderungen eines Benutzers ohne das belegartspezifische Preisänderungsrecht beim Speichern auf die Werte der Vorgängerversion zurücksetzen, statt den Speichervorgang abzulehnen.
Ergebnis: Ein Benutzer ohne Preisänderungsrecht kann den Beleg speichern; die Preise entsprechen danach den Werten vor seiner Änderung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3694 (`UpdateArticlePositionsPurchasePriceAndSellPriceIfUserDoesNotHaveRightToChangeThem`) - Begründung: Der Methodenname und die Parameter (`currentUser`, `previousReceiptVersion`) belegen die Rücksetzungsstrategie unmittelbar.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2204-2205, 2236-2237, 2264-2265, 2296, 2315-2316, 2340, 2383 - Begründung: Belegt die belegartspezifische Trennung von Einkaufs- und Verkaufspreisrecht.
Prüfidee: Ein Benutzer ohne `Order.CHANGE_PRICE` ändert einen Auftragspositionspreis und speichert; nach dem Neuladen steht der ursprüngliche Preis.
Tracelinks: SyRS-017, SyRS-021; StRS-002, StRS-005, StRS-015
Konsolidierung: Kandidat: Sieben belegartspezifische Rechtepaare bilden dieselbe fachliche Regel ab; im Zielsystem als ein Recht mit Belegart-Geltungsbereich zusammenführbar.
Status: belegt
```
```
ID: SwRS-020
Titel: Datenmodell der Provisionsermittlung
Ebene: SwRS
Typ: Daten
Akteur: Fachbereich Provision
Vorbedingung: –
Fakt: Das Provisionsmodell umfasst sieben Entitäten unter `src/backend/Centron.Entities/Entities/Sales/Receipts/`: `ReceiptProvisionSchema` (Schema), `ReceiptProvisionSchemaItem` (Schemazeile), `ReceiptProvisionSchemaCustomerAssignment` (Kundenzuordnung), `ReceiptProvisionItemEntity` (ermittelter Provisionswert je Belegposition), `ReceiptProvisionEmployeeGoal` (Mitarbeiterziel), `ReceiptProvisionEmployeeLevel` (Mitarbeiterstufe). Die Berechnung erfolgt in `ReceiptProvisionBL`, die Schemaverwaltung in `ReceiptProvisionSchemaBL`. Schemas besitzen eine zeitliche Gültigkeit, die vom Hintergrunddienst `UpdateExpiredProvisionSchemasService` stündlich fortgeschrieben wird.
Aussage: Das System soll Provisionsschemas mit Zeilen, Kundenzuordnung und mitarbeiterbezogenen Zielen und Stufen führen und ermittelte Provisionswerte je Belegposition persistieren.
Ergebnis: Zu jeder provisionsrelevanten Belegposition ist der ermittelte Provisionswert und das zugrunde liegende Schema nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvisionSchema.cs, ReceiptProvisionSchemaItem.cs, ReceiptProvisionSchemaCustomerAssignment.cs, ReceiptProvisionItemEntity.cs, ReceiptProvisionEmployeeGoal.cs, ReceiptProvisionEmployeeLevel.cs - Begründung: Vollständiges Entitätenmodell der Domäne.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptProvisionBL.cs, ReceiptProvisionSchemaBL.cs - Begründung: Zugehörige Fachlogikkomponenten.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/UpdateExpiredProvisionSchemasService.cs - Begründung: Belegt die zeitliche Gültigkeit als aktiv verwaltetes Merkmal.
Prüfidee: Nach Belegerfassung existiert je provisionsrelevanter Position ein `ReceiptProvisionItemEntity`-Datensatz mit Verweis auf das angewandte Schema.
Tracelinks: SyRS-013; StRS-016
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-021
Titel: Getrennte Auswertungskomponenten je Statistikart
Ebene: SwRS
Typ: funktional
Akteur: Fachbereich Statistik
Vorbedingung: –
Fakt: Auswertungen sind auf drei Ebenen getrennt: `src/backend/Centron.BL/Statistics/` (16 Klassen, u. a. `ContractStatistics/ContractEvaluationBL.cs` mit 87 KB), `src/backend/Centron.Entities/Entities/Statistics/` (35 Entitäten) und `src/backend/Centron.DAO/Statistics/`. Die Auswertung wird über `ReportDataBL` (92 KB) und die Berichtsmaschine (`src/backend/Centron.BL/ReportEngine/`, 26 Klassen; `Centron.Interfaces/ReportEngine`, `CentronReportEngine`) an ein Berichtsformat übergeben. Es existiert ein Modul „Reportserver" mit Recht `REPORTSERVER = 20800044` sowie das Recht `UPLOAD_PORTAL_REPORTS = 99999458`, dessen Kommentar es als Sonderrecht ausschließlich in c-entron-eigenen Datenbanken ausweist.
Aussage: Das System soll Auswertungsdaten, Auswertungslogik und Berichtsdarstellung in getrennten Komponenten führen und die Berichtsvorlagenverwaltung als eigenständig berechtigte Funktion bereitstellen.
Ergebnis: Eine Änderung an einer Berichtsvorlage erfordert keine Änderung an der Auswertungslogik.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Statistics/, src/backend/Centron.BL/ReportEngine/, src/backend/Centron.DAO/Statistics/, src/backend/Centron.Entities/Entities/Statistics/ - Begründung: Physische Trennung der drei Ebenen.
- [PRIMÄR] src/backend/Centron.BL/ReportEngine/ReportDataBL.cs (92 KB, `ConvertReportToPdfStream`, `ArchivePdf`) - Begründung: Zentrale Berichtserzeugung.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:21 (`UPLOAD_PORTAL_REPORTS` mit Kommentar „Special Right: Only in c-entron databases …") - Begründung: Belegt ein herstellerinternes Sonderrecht.
Prüfidee: Ein Bericht kann ohne Änderung an `ContractEvaluationBL` neu gestaltet werden.
Tracelinks: SyRS-013; StRS-017
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-022
Titel: Lokalisierung über Ressourcendateien je Assembly
Ebene: SwRS
Typ: Daten
Akteur: Alle Anwendungsteile
Vorbedingung: Ein anwendersichtbarer Text wird ausgegeben.
Fakt: Es existieren sieben Ressourcenpaare: `Centron.BL/Resources/LocalizedStrings.resx|.en.resx` (26/24 KB), `Centron.WPF.UI/Resources/LocalizedStrings.resx|.en.resx` (404/349 KB), `Centron.Controls/Resources/LocalizedStrings.resx|.en.resx` (129/125 KB), `CentronNexus/SharedResource.resx|.en-US.resx` (7/7 KB), `CentronNexus/WebCart/Resource/WebCartResource.resx|.en-us.resx` (19/18 KB), `CentronNexus/WebCart/Resource/CountriesResource.resx|.en-us.resx` (16/16 KB), `CentronNexus.OutlookAddIn/SharedResource.resx` (1 KB, ohne englische Fassung). Der Zugriff erfolgt über die generierte Klasse `LocalizedStrings.Designer.cs` (53 KB in `Centron.BL`). Die Pflege wird durch `ResXManager.config.xml` unterstützt.
Aussage: Das System soll anwendersichtbare Texte je Assembly in eigenen Ressourcendateien führen, sodass Backend-, Client- und Portaltexte unabhängig voneinander gepflegt werden können.
Ergebnis: Ein Text ist über einen typisierten Bezeichner (`LocalizedStrings.<Schlüssel>`) erreichbar; die Sprachfassung wird zur Laufzeit anhand der Spracheinstellung gewählt.
Belege:
- [PRIMÄR] Auflistung aller `*.resx` außerhalb von `bin`/`obj` mit Pfaden und Größen - Begründung: Belegt Aufteilung und Umfang objektiv.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:74, 82, 103, 164-165, 202 (`LocalizedStrings.<Schlüssel>`) - Begründung: Belegt die typisierte Verwendung im Backend.
- [SEKUNDÄR] ResXManager.config.xml - Begründung: Werkzeugunterstützung der Ressourcenpflege.
- [KONTEXT] docs/guides/ui/localization.md - Begründung: Beschreibt die Verwendung in XAML, Code-Behind und Fachlogik.
Prüfidee: Ein Wechsel der Spracheinstellung auf Englisch ändert die Beschriftungen im WPF-Client; für Schlüssel ohne englische Entsprechung bleibt der deutsche Text stehen.
Tracelinks: SyRS-048; StRS-018
Konsolidierung: Kandidat: Sieben getrennte Ressourcenbestände mit teilweise gleichlautenden Texten; im Zielsystem als ein Übersetzungsbestand zusammenführbar.
Status: belegt
```
```
ID: SwRS-023
Titel: Drei austauschbare Hostvarianten für den Web-Service
Ebene: SwRS
Typ: funktional
Akteur: Web-Service
Vorbedingung: –
Fakt: Die Serverfunktionalität liegt in `Centron.Host` (`net10.0`, `CentronHost.cs`) und wird von drei Startprojekten gehostet: `Centron.Host.Console` (Konsolenanwendung, in Docker über `command: /app/Centron.Host.Console` gestartet), `Centron.Host.WindowsService` (Windows-Dienst) und – für die moderne API – `Centron.Controllers`, das in denselben Prozess eingebunden ist. Echtzeitfunktionen laufen über SignalR-Hubs (`AvailabilityStatusHub`, `ChatHub`, `NotificationsHub`, `TapiClientHub`) mit einer schlüsselbasierten Autorisierung (`SecretKeyHandler`, `SecretKeyRequirement`), deren Schlüssel in `WebServiceConfig.xml` als `<SecretKey>` und in der Portalkonfiguration als `Notifications.SecretKey` hinterlegt ist.
Aussage: Das System soll die Serverfunktionalität unabhängig von der Hostvariante bereitstellen und Echtzeitbenachrichtigungen über eine schlüsselgesicherte Verbindung zwischen Portal und Web-Service austauschen.
Ergebnis: Dieselbe Serverfunktionalität ist über Konsolenprozess und Windows-Dienst identisch verfügbar; Echtzeitkanäle sind nur mit korrektem gemeinsamem Schlüssel nutzbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs, Centron.Host.Console/, Centron.Host.WindowsService/ - Begründung: Belegt die Trennung von Funktionalität und Hostvariante.
- [PRIMÄR] src/webservice/Centron.Host/RealTimeServices/ (`AvailabilityStatusHub`, `ChatHub`, `NotificationsHub`, `TapiClientHub`, `SecretKeyHandler`, `SecretKeyRequirement`) - Begründung: Belegt Echtzeitkanäle und deren Autorisierungsmechanismus.
- [PRIMÄR] docker/compose/WebServiceConfig.xml (`<SecretKey>` mit Base64-Wert) und src/nexus/CentronNexus.Host/appsettings.json (`Notifications.SecretKey`) - Begründung: Belegt den gemeinsamen Schlüssel als Konfigurationsgegenstück.
- [PRIMÄR] docker/compose/compose.yaml (`command: /app/Centron.Host.Console`) - Begründung: Belegt die Konsolenvariante als Containerstartpunkt.
Prüfidee: Ein Portal mit falschem `Notifications.SecretKey` erhält keine Echtzeitbenachrichtigungen; die übrige Funktionalität bleibt nutzbar.
Tracelinks: SyRS-035, SyRS-040; StRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-024
Titel: Einheitliche Anbieterstruktur der externen Artikelsuche
Ebene: SwRS
Typ: Schnittstelle
Akteur: Komponente Artikelsuche
Vorbedingung: Eine Artikelsuche mit externer Quelle wird ausgeführt.
Fakt: Unter `src/backend/Centron.BL/Sales/Receipts/ArticleSearch/` liegen `ArticleSearchBL` (56 KB), `SearchTextParser` (18 KB) und drei Anbieterklassen mit gleichlautendem Namensmuster: `ITscopeExternalArticleSearchProvider` (14 KB), `EgisExternalArticleSearchProvider` (18 KB), `CopApiBaseExternalArticleSearchProvider` (10 KB). Die eigentlichen Protokollimplementierungen liegen in eigenen Projekten unter `src/apis/` mit jeweils gleicher Binnenstruktur (`Data/`, `Parser/`, `Properties/`, teils `SoapTemplates/` bzw. `RequestTemplates/`).
Aussage: Das System soll externe Artikelquellen über gleichartig aufgebaute Anbieterkomponenten einbinden, deren Protokoll- und Auswertungslogik von der Suchlogik getrennt ist.
Ergebnis: Eine neue externe Quelle erfordert eine neue Anbieterklasse und ein neues Zugriffsprojekt, aber keine Änderung an `ArticleSearchBL`.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ArticleSearch/ (drei Anbieter mit gleichem Namensmuster) - Begründung: Belegt die einheitliche Anbieterstruktur.
- [PRIMÄR] src/apis/Centron.APIs.ITscopeDataAccess/, .EgisDataAccess/, .CopDataAccess/, .IcecatDataAccess/ (je `Data/`, `Parser/`) - Begründung: Belegt die gleichartige Binnenstruktur der Zugriffsprojekte.
- [PRIMÄR] tests/apis/ (vier Testprojekte, je eines pro externem Zugriffsprojekt) - Begründung: Belegt die eigenständige Testbarkeit je Anbieter.
Prüfidee: Alle drei Anbieterklassen implementieren dieselbe Schnittstelle und liefern strukturgleiche Ergebnisobjekte an `ArticleSearchBL`.
Tracelinks: SyRS-034; StRS-020
Konsolidierung: Kandidat: Siehe StRS-020 – im Zielsystem als ein Anbietervertrag mit einheitlichem Ergebnismodell.
Status: belegt
```
---
## 3. Sicherheitsrelevante Softwareinterna
```
ID: SwRS-025
Titel: Vererbungsstruktur der Authentifikatoren
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `Authenticator`
Vorbedingung: –
Fakt: Alle Authentifikatoren erben von der abstrakten Klasse `Authenticator(DAOSession, AuthObject, ILicenseManager) : BaseBL, IAuthenticator`, die den gemeinsamen Ablauf `Authenticate()` → `GetTicket()` → `AuthenticateUser(...)` mit Rechteprüfung, Lizenzprüfung, Ticketerzeugung, IP-Vermerk und Versionsprotokollierung vorgibt. Nur `AuthenticateInternal()` ist abstrakt. Implementierungen: `BasicAuthenticator` (Benutzerstamm), `ActiveDirectoryAuthenticator` (12 KB), `OpenIdConnectAuthenticator`, `WebAccountAuthenticator`, `FallbackAuthenticator` (Kette), `FailingAuthenticator` (immer fehlschlagend mit Meldung). Das Basisobjekt `AuthObject` trägt `RequestId` (GUID je Anmeldeversuch), `RemoteAddress`, `AppVersion`, `ApplicationName`, `MachineName` und überschreibt `ToString()` zur Protokollierung.
Aussage: Das System soll den sicherheitsrelevanten Anmeldeablauf einmalig in einer Basisklasse festlegen, sodass jede Authentifizierungsart dieselben Rechte-, Lizenz- und Protokollierungsschritte durchläuft und nur die Identitätsprüfung austauschbar ist.
Ergebnis: Eine neue Authentifizierungsart erbt automatisch Rechte-, Lizenz- und Ticketlogik; Umgehungen sind nicht möglich, ohne die Basisklasse zu verändern.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:51-155 (abstrakte Basisklasse mit festgelegtem Ablauf, nur `AuthenticateInternal` abstrakt) - Begründung: Belegt den Schablonenmethoden-Ansatz unmittelbar.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs:21-43 (`AuthObject` mit `RequestId` und `ToString()`) - Begründung: Belegt die durchgängige Nachvollziehbarkeit jedes Anmeldeversuchs über eine Vorgangskennung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/ (6 Implementierungen) - Begründung: Belegt den Umfang der Austauschbarkeit.
Prüfidee: Für jede Authentifikator-Implementierung wird bei erfolgreicher Anmeldung genau ein Ticket erzeugt und die Lizenzprüfung durchlaufen; die `RequestId` erscheint in allen Protokolleinträgen desselben Anmeldeversuchs.
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SyRS-006; StRS-022
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-026
Titel: Ablage und Prüfung von Benutzerkennwörtern
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponenten `BasicAuthenticator`, `WebAccountBL`
Vorbedingung: Ein Benutzer meldet sich mit Benutzername und Kennwort an.
Fakt: `BasicAuthenticator.AuthenticateInternal` bildet über `SHA1Decoder.GetDecodedSHA1String(Auth.Password)` einen SHA-1-Wert und sucht damit direkt den Benutzerdatensatz: `GetEntity(where => where.Name == Auth.UserName && where.Password == decodedPassword)`. Unmittelbar darüber steht der Quelltextkommentar `// TODO the password should be salted!!!`. `WebAccountBL.LoginWithWebAccount` verwendet dasselbe Verfahren (`SHA1Decoder.GetDecodedSHA1String(password)`, Vergleich `f.Password == cryptedPw`) für Portalkonten. Es findet kein Vergleich in konstanter Zeit statt; das Kennwort ist Teil der Datenbankabfrage.
Aussage: [HYPOTHESE] Das System soll Benutzerkennwörter mit einem benutzerindividuellen Zufallswert (Salt) und einem für Kennwörter geeigneten, rechenintensiven Verfahren ableiten und speichern; der derzeit verwendete ungesalzene SHA-1-Wert erfüllt diese Anforderung nicht.
Ergebnis: Kennwörter sind gegen Rainbow-Table- und Offline-Angriffe geschützt; ein Datenbankabzug erlaubt keine praktikable Rückrechnung.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs:46-50 (`SHA1Decoder.GetDecodedSHA1String`, Vergleich in der Abfrage, Kommentar `// TODO the password should be salted!!!`) - Begründung: Belegt Verfahren und die den Entwicklern bekannte Unzulänglichkeit unmittelbar im Code.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebAccountBL.cs:56-61 (dasselbe Verfahren für Web-Accounts) - Begründung: Belegt, dass der Mangel beide Kontoarten betrifft.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:166-170 (`CryptoUtils.CreateSalt(32)`, `CryptoUtils.CreatePasswordHash(deviceId, salt)`) - Begründung: Belegt, dass eine gesalzene Ableitungsfunktion im System vorhanden ist, aber nur für Ticketkennungen und nicht für Kennwörter verwendet wird.
- [KONTEXT] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs:1263 (`contact.WebKennwort = null`) - Begründung: Belegt, dass Portalkennwörter als personenbezogenes Datum an der Kontaktentität geführt werden.
Prüfidee: Zwei Benutzer mit identischem Kennwort besitzen in der Datenbank denselben Kennwortwert – der Nachweis bestätigt das Fehlen eines Salts. Zielzustand: unterschiedliche Werte bei identischem Kennwort.
Tracelinks: SyRS-003; StRS-002, StRS-011, StRS-022
Konsolidierung: Kandidat: Zwei getrennte Kennwortprüfungen (`BasicAuthenticator` für Mitarbeiter, `WebAccountBL` für Portalkonten) mit identischem Verfahren; im Zielsystem als ein Identitätsdienst zusammenzuführen.
Status: HYPOTHESE
Fehlende Information: Der **Ist-Zustand** (ungesalzenes SHA-1, Vergleich in der Datenbankabfrage) ist durch `PRIMÄR`-Belege eindeutig nachgewiesen. Als `[HYPOTHESE]` gekennzeichnet ist ausschließlich die **Soll-Aussage**: Ob eine Umstellung auf ein gesalzenes, rechenintensives Verfahren im Zielsystem möglich ist, hängt von der Migrationsstrategie für bestehende Kennwörter und von der Kompatibilität mit der Delphi-Vorgängeranwendung ab, die denselben Benutzerstamm nutzt. Diese Randbedingung ist aus den Artefakten nicht ableitbar und durch Fachexperten zu klären.
```
```
ID: SwRS-027
Titel: Portalkomponenten der Dokumentensignatur
Ebene: SwRS
Typ: funktional
Akteur: Webportal
Vorbedingung: –
Fakt: Die Signaturfunktion besteht aus `DocumentSigningPage.razor` (Seitenkomponente mit eigenem `.razor.css`) und `IsolatedSignaturePad.razor` (gekapselte Unterschriftenfläche). Die zugehörigen Serveraufrufe sind `GetSharedDocumentByToken`, `SharedDocumentAccepted` und `SignSharedDocument` in der Legacy-REST-Schnittstelle. Für Ticketsignaturen existiert zusätzlich das Recht `DELETE_HELPDESK_SIGNATURE = 20800143` („Unterschrift aus Zeit löschen"). Objektarten: `DocumentSigning = 7600133`, `DocumentSigningCustomerReceipts = 7600146`.
Aussage: Das System soll die Unterschriftenerfassung als eigenständige, gekapselte Oberflächenkomponente bereitstellen, deren Ergebnis über einen tokengebundenen Serveraufruf am Geschäftsobjekt festgehalten wird; das Entfernen einer erfassten Unterschrift soll ein eigenes Recht erfordern.
Ergebnis: Eine erfasste Unterschrift ist dem Dokument bzw. der Ticketzeit zugeordnet und kann nur mit dem Löschrecht entfernt werden.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor, DocumentSigningPage.razor.css - Begründung: Belegt die gekapselte Oberflächenkomponente.
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetSharedDocumentByToken`, `SharedDocumentAccepted`, `SignSharedDocument`) - Begründung: Belegt den tokengebundenen Serveraufruf.
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:1974 (`DELETE_HELPDESK_SIGNATURE = 20800143`) - Begründung: Belegt das eigenständige Löschrecht.
- [KONTEXT] CentronRights.md:55-57 („Unterschrift aus Zeit löschen") - Begründung: Fachliche Beschreibung des Rechts.
Prüfidee: Eine im Portal erfasste Unterschrift ist nach dem Speichern am Beleg sichtbar; ein Benutzer ohne `DELETE_HELPDESK_SIGNATURE` kann sie nicht entfernen.
Tracelinks: SyRS-010; StRS-023
Konsolidierung: nein
Status: belegt
```
---
## 4. Konfiguration, Betrieb, Build
```
ID: SwRS-028
Titel: Typisierter Zugriff auf Anwendungseinstellungen über Gruppenklassen
Ebene: SwRS
Typ: Daten
Akteur: Komponente `AppSettingsBL` / `AppSettingsGroupBL`
Vorbedingung: Eine Fachkomponente benötigt Konfigurationswerte.
Fakt: Fachkomponenten greifen nicht direkt auf die Einstellungstabellen zu, sondern über `AppSettingsBL.GetSettings(params ApplicationSettingID[])` bzw. `GetSettings(AppSettingsConst)` und lesen typisiert mit `GetBool(id, default)`, `GetInt`, `GetString`, `GetLargeString`, `GetEnum<T>`, `GetDecimal`. Schreibzugriffe laufen über `GetSettingsForUpdate(...)`, `Update*` und `SaveSettings()`. Zusammengehörige Einstellungen werden in Gruppenklassen gebündelt (`AppSettingsGroupBL`, 153 KB; `AppSettingsGroupWebServiceBL`), die typisierte DTOs wie `ReceiptInvoiceSettingsDTO`, `JwtSettings`, `AuthenticationSettings`, `TextBlockSettings` liefern.
Aussage: Das System soll den Zugriff auf Anwendungseinstellungen ausschließlich über typisierte Gruppenklassen führen, die Standardwerte bei fehlendem Eintrag liefern, sodass Fachkomponenten keine Kenntnis der Speicherstruktur benötigen.
Ergebnis: Eine fehlende Einstellung führt nicht zu einem Fehler, sondern zum hinterlegten Standardwert; die Speicherstruktur ist für die Fachkomponente unsichtbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:34, 38, 46 (`_appSettingsBL.GetJwtSettings()`, `GetAuthenticationSettings()`) - Begründung: Belegt die Gruppenklassen im sicherheitskritischen Pfad.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:233-238 (`GetSettings(...).GetBool(..., false)`) - Begründung: Belegt typisierten Zugriff mit Standardwert.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs:151-152, 233-245 (`GetSettings(AppSettingsConst.TicketReleaseTime).GetInt(...)`, `GetSettingsForUpdate(...)`, `UpdateInt`, `SaveSettings`) - Begründung: Belegt Lese- und Schreibpfad.
- [KONTEXT] docs/guides/development/settings-management.md:63-115, 147-156 - Begründung: Beschreibt Gruppenklassen, Datentypen und Standardwertregel als Projektvorgabe.
Prüfidee: Das Löschen eines Einstellungsdatensatzes führt beim nächsten Lesen zum im Code angegebenen Standardwert und nicht zu einem Fehler.
Tracelinks: SyRS-049; StRS-024
Konsolidierung: Kandidat: `AppSettingsConst` (728 Einträge, Tabelle `Stammdat`) und `ApplicationSettingID` (492 Einträge, Tabelle `ApplicationSettings`) bilden dieselbe fachliche Funktion ab; die Zusammenführung ist im Zielsystem zwingend.
Status: belegt
```
```
ID: SwRS-029
Titel: Gemeinsame Basisklasse aller Hintergrunddienste
Ebene: SwRS
Typ: funktional
Akteur: Web-Service-Host
Vorbedingung: –
Fakt: Alle 35 Hintergrunddienste erben von `ManagedBackgroundService : BackgroundService` und implementieren nur `ServiceName` (Bezeichner für Aktivierung und Protokollierung), `GetExecutionInterval()` (Grundintervall) sowie wahlweise `ExecuteService`/`ExecuteServiceAsync` und `InitializeService`/`InitializeServiceAsync`. Belegte Grundintervalle: 1 Minute (`TelemetryFlushService`, `ObjectFulltextIndexUpdateService`, `DocumentFulltextIndexUpdateService`) und 1 Stunde (`DataQualityService`, `ValidateHelpdeskFingerprintService`, `UpdateExpiredProvisionSchemasService`, `UpdateArticleAndMaterialGroupTaxRatesService`, `RefreshIntakeService`, `PlmImportService`). Die Basisklasse übernimmt Anlaufverzögerung, Aktivierungsprüfung, Ausnahmebehandlung, Rücknahme der Aufruffrequenz und Laufzeitprotokollierung.
Aussage: Das System soll für alle Hintergrunddienste dieselbe Basisklasse verwenden, sodass Aktivierung, Fehlerbehandlung, Frequenzrücknahme und Laufzeitprotokollierung einheitlich sind und ein Dienst nur seine fachliche Aufgabe und sein Intervall festlegt.
Ergebnis: Ein neuer Hintergrunddienst benötigt zwei Überschreibungen; Betriebsverhalten und Überwachbarkeit sind ohne Zusatzaufwand gegeben.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:12-30, 159-179 (Vertrag der Basisklasse) - Begründung: Belegt den minimalen Implementierungsaufwand je Dienst.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/DataQualityService.cs:22 (`: ManagedBackgroundService`) - Begründung: Konkreter Nachweis der Vererbung.
- [PRIMÄR] Intervallwerte in TelemetryFlushService.cs:21, ObjectFulltextIndexUpdateService.cs:51, DocumentFulltextIndexUpdateService.cs:43, ValidateHelpdeskFingerprintService.cs:64, UpdateExpiredProvisionSchemasService.cs:45, UpdateArticleAndMaterialGroupTaxRatesService.cs:75, RefreshIntakeService.cs:31, PlmImportService.cs:64 - Begründung: Belegt die tatsächlich verwendeten Taktungen.
- [KONTEXT] docs/Background Service/DataQualityService.md:23-68 (Regeln für Sitzungsverwaltung, Fehlerbehandlung, Abbruchprüfung) - Begründung: Formuliert die Implementierungsregeln je Aufgabe.
Prüfidee: Jede Klasse in `HostedServices/` außer `ManagedBackgroundService` erbt von dieser und überschreibt `ServiceName` und `GetExecutionInterval`.
Tracelinks: SyRS-035, SyRS-045; StRS-025
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-030
Titel: Umschlagtypen und Sichtbarkeitsstruktur der Legacy-Schnittstelle
Ebene: SwRS
Typ: Schnittstelle
Akteur: Legacy-REST-Schnittstelle
Vorbedingung: –
Fakt: Alle Legacy-Methoden verwenden ausschließlich POST und die Umschlagtypen `Request` / `Request<T>` für Eingaben und `Response` / `Response<T>` für Ausgaben; die Nutzdaten liegen im Feld `Data`. Zusätzlich tragen viele Methoden `[Category("…")]` und `[Description("…")]` zur Gruppierung in der eingebauten Hilfeseite (`Centron.Host/HelpPage/`, aktivierbar über `<ActivateHelpPage>` in `WebServiceConfig.xml`). Die Vertragsdefinition ist auf 31 Dateien verteilt (Hauptdatei 358 KB, 30 domänenbezogene Partialdateien), die Implementierung auf 35 Dateien (Hauptdatei 171 KB, DTO-Teil 324 KB). Bekannte Typen für die Serialisierung werden zentral in `KnownTypes.cs` (14 KB) registriert. Es existiert `GetWebServiceMethodList`, das eine Metadatenliste aller Methoden liefert.
Aussage: Das System soll die Legacy-Schnittstelle mit einheitlichen Umschlagtypen, ausschließlich über POST und mit selbstbeschreibenden Metadaten bereitstellen, damit Clients generisch gegen sie programmieren können.
Ergebnis: Ein Client kann jede Methode nach demselben Muster aufrufen; die verfügbaren Methoden sind über `GetWebServiceMethodList` und die Hilfeseite ermittelbar.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/Services/CentronRestServiceInterfaceParts/ICentronRestService.Receipts.cs:100-138 (`[WebInvoke(Method = "POST", UriTemplate = "…")]`, `Response<T>`/`Request<T>`, `[Category]`, `[Description]`) - Begründung: Repräsentativer Ausschnitt mit allen Merkmalen.
- [PRIMÄR] src/webservice/Centron.Host/Services/KnownTypes.cs - Begründung: Belegt die zentrale Typregistrierung als Voraussetzung der Serialisierung.
- [PRIMÄR] src/webservice/Centron.Host/HelpPage/ und docker/compose/WebServiceConfig.xml (`<ActivateHelpPage>false</ActivateHelpPage>`) - Begründung: Belegt die eingebaute, abschaltbare Selbstbeschreibung.
- [PRIMÄR] src/webservice/Centron.Host/Services/ICentronRestService.cs (`GetWebServiceMethodList`, ohne `[Authenticate]`) - Begründung: Belegt die maschinenlesbare Methodenliste – und zugleich, dass sie unauthentifiziert abrufbar ist.
- [KONTEXT] docs/reference/architecture/requests-and-responses.md - Begründung: Beschreibt die Umschlagtypen.
Prüfidee: Ein Aufruf von `GetWebServiceMethodList` liefert 2 599 Einträge; jeder Eintrag ist per POST unter `UriTemplate` erreichbar.
Tracelinks: SyRS-010, SyRS-011, SyRS-031; StRS-001
Konsolidierung: Kandidat: Siehe SyRS-031 – Ablösung durch die moderne Schnittstelle.
Status: belegt; Workaround (Die durchgängige Verwendung von POST auch für reine Leseoperationen und die Umschlagtypen sind Artefakte der ursprünglichen WCF-Implementierung und nicht HTTP-konform; im Zielsystem durch ressourcenorientierte Endpunkte zu ersetzen.)
```
```
ID: SwRS-031
Titel: Fassade für Datenzugriff und Fachlogik über die Sitzung
Ebene: SwRS
Typ: funktional
Akteur: Backend
Vorbedingung: Eine Fachoperation wird ausgeführt.
Fakt: Der Datenzugriff läuft über `BLSession`/`DAOSession` mit den Zugriffswegen `GetBL<T>()` (Fachlogikkomponente), `GetGenericDAO<TEntity>()` (generischer Entitätszugriff mit `GetEntity`, `GetEntityList`, `SaveOrUpdate`, `Delete`), `GetDAO<TRepository>()` (spezialisiertes Repository), `GetSession()` (direkter NHibernate-Zugriff mit LINQ), `Session.Advanced.RawSqlAccess` (parametrisiertes Roh-SQL über `ExecuteQuery<T>`, `ExecuteScalarTransactionSave<T>`, `ExecuteNonQueryTransactionSave`) und `Session.Advanced.Cache` (`GetOrAdd`). Transaktionen werden über `Session.WithTransaction(() => …)` bzw. `StartTransaction`/`RollbackTransaction` geklammert. Sitzungen sind kurzlebig und werden mit `using` freigegeben.
Aussage: Das System soll den gesamten Datenzugriff über eine Sitzungsfassade führen, die Fachlogik, generischen Entitätszugriff, spezialisierte Repositories, parametrisiertes Roh-SQL, Zwischenspeicher und Transaktionsklammer an einer Stelle bereitstellt.
Ergebnis: Eine Fachkomponente benötigt keine eigene Verbindungs- oder Transaktionsverwaltung; Roh-SQL ist ausschließlich über die parametrisierte Fassade möglich.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:105-110, 658-662 (`RawSqlAccess.ExecuteQuery<CustomClass>` mit `NamedQueryParameter`) - Begründung: Belegt parametrisiertes Roh-SQL als vorgesehenen Weg.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:3544, 3074, 3179, 3206 (`Session.WithTransaction`, `StartTransaction`, `RollbackTransaction`) - Begründung: Belegt die Transaktionsklammer.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7291-7306 (`Session.Advanced.Cache.GetOrAdd` mit parametrisiertem SQL) - Begründung: Belegt die Kombination aus Zwischenspeicher und Roh-SQL.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:42-46, 69-74 (`using (var session = new BLSession())`) - Begründung: Belegt die kurzlebige Sitzungsverwendung.
Prüfidee: Keine Fachkomponente öffnet eine eigene `SqlConnection`; alle SQL-Ausführungen laufen über `Session.Advanced.RawSqlAccess` mit benannten Parametern.
Tracelinks: SyRS-012, SyRS-017, SyRS-033; StRS-001
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-032
Titel: Zeichenkettenverkettung in generierten SQL-Anweisungen der Nummernvergabe
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `NumberGroupBL`
Vorbedingung: Eine neue Nummer wird aus einem Nummernkreis ermittelt.
Fakt: `NumberGroupBL.FindNextNumber` erzeugt seine Prüfabfragen durch Zeichenkettenverkettung statt über Parameter: `$"SELECT COUNT(*) AS cnt FROM {tableName} WHERE {fieldName} = '{counter}'"` bzw. `… = {counter}` sowie `$"SELECT COUNT(*) AS cnt FROM dbo.Kunden WHERE I3D = {counter}"`. Die eingesetzten Werte stammen aus `numberGroup.GetTableName()`, `numberGroup.GetFieldName()` (beide aus der Aufzählung `NumberGroupEnum` abgeleitet, nicht aus Benutzereingaben) und `counter` (Ganzzahl). Im übrigen Code wird dagegen konsequent parametrisiert gearbeitet (`NamedQueryParameter`, `AddParameter`).
Aussage: Das System soll alle SQL-Anweisungen parametrisiert erzeugen; die Verkettung von Werten in Anweisungstexte ist auch dann zu vermeiden, wenn die Werte derzeit aus vertrauenswürdigen Quellen stammen.
Ergebnis: Kein SQL-Anweisungstext enthält interpolierte Werte; Tabellen- und Spaltennamen stammen aus einer Positivliste.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:107-131 (drei interpolierte SQL-Anweisungen) - Begründung: Belegt die Abweichung vom sonst durchgängigen Parametrisierungsmuster.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7295-7305 (parametrisierte Alternative im selben Projekt: `f.AddParameter("CustomerI3D", customerI3D)`) - Begründung: Belegt, dass das sichere Muster verfügbar ist und andernorts verwendet wird.
- [KONTEXT] docs/reference/database/script-rules.md:135-138 („When direct SQL is needed, ensure proper schema references and SQL injection protection") - Begründung: Formuliert die Regel als Projektvorgabe, die hier nicht eingehalten ist.
Prüfidee: Eine statische Codeanalyse auf interpolierte SQL-Zeichenketten meldet die drei Stellen in `NumberGroupBL`; nach Umstellung auf Parameter meldet sie keine.
Tracelinks: SyRS-018; StRS-005
Konsolidierung: nein
Status: belegt; Workaround (Die derzeitigen Eingangswerte – Aufzählungswerte und Ganzzahlen – sind nicht angreifbar; die Konstruktion widerspricht jedoch der projekteigenen Regel und ist bei künftigen Erweiterungen der Aufzählung ein Risiko.)
```
```
ID: SwRS-033
Titel: Skriptbasierte, idempotente Schemafortschreibung
Ebene: SwRS
Typ: Daten
Akteur: Komponente `ScriptEngineBL`
Vorbedingung: Der Web-Service startet.
Fakt: Die Schemafortschreibung besteht aus `ScriptEngineBL`, `ScriptMethodPool`, `ScriptMethodKind`, `ScriptSpecialObjects`, `ScriptHelpers`, den Basisklassen `BaseScriptMethod` und `BaseRecurringScriptMethod` sowie den Schnittstellen `IScriptMethod` und `IRecurringScriptMethod`. Es existieren 764 einmalige Skripte `ScriptMethod{Nummer}.cs`; die Nummernvergabe erfolgt laut Projektdokumentation über eine externe Excel-Liste. `BaseRecurringScriptMethod` erlaubt zusätzlich wiederkehrend auszuführende Skripte, die vom Hintergrunddienst `RecurringScriptService` gestartet werden. `ScriptHelpers` erzeugt bedingte DDL-Anweisungen; für indizierte Spalten existiert `AlterColumnTypeIndexSafe`.
Aussage: Das System soll Schemaänderungen als nummerierte, unabhängige und wiederholbar ausführbare Skripte führen und zwischen einmalig und wiederkehrend auszuführenden Skripten unterscheiden.
Ergebnis: Eine Datenbank beliebigen Ausgangsstands erreicht nach dem Start den aktuellen Strukturstand; eine erneute Ausführung ändert nichts.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs, ScriptMethods/ScriptMethodPool.cs, ScriptMethods/BaseScriptMethod.cs, BaseRecurringScriptMethod.cs, IScriptMethod.cs, IRecurringScriptMethod.cs, ScriptHelpers.cs, ScriptMethodKind.cs, ScriptSpecialObjects.cs - Begründung: Vollständige Komponentenmenge des Mechanismus.
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/ (764 Dateien) - Begründung: Umfang der Schemahistorie.
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/RecurringScriptService.cs - Begründung: Belegt die wiederkehrende Skriptausführung als eigenen Dienst.
- [KONTEXT] docs/reference/database/script-rules.md:7-58, 129-141 - Begründung: Beschreibt Ablage, Nummernvergabe, Hilfsmethoden und Idempotenzregel.
Prüfidee: Alle 764 Skriptdateien enthalten ausschließlich bedingte DDL-Anweisungen bzw. `ScriptHelpers`-Aufrufe; eine zweite Ausführung erzeugt keine Änderung.
Tracelinks: SyRS-039; StRS-019
Konsolidierung: nein
Status: belegt; Workaround (Die Skriptnummernvergabe erfolgt über eine repository-externe Excel-Liste; damit ist die Eindeutigkeit nicht durch das Versionsverwaltungssystem gesichert.)
```
```
ID: SwRS-034
Titel: Zweistufige Serverkonfiguration aus Datei und Datenbank
Ebene: SwRS
Typ: Daten
Akteur: Web-Service
Vorbedingung: –
Fakt: Die Serverkonfiguration ist auf zwei Orte verteilt: (a) die Datei `WebServiceConfig.xml`, gelesen über `WebServiceConfigHelper.Current`, mit den Feldern `WebServiceAddress`, `PublicWebServiceAddress`, `WebServiceCertificateFilePath`, `WebServiceCertificatePassword`, `ActiveDirectoryAuthEnabled`, `ActiveDirectoryUrl`, `ActiveDirectoryName`, `ActiveDirectoryCertificateHash`, `DatabaseConnectionString`, `DatabaseConnectionStringPlain`, `UseIncreasedThreadPool`, `ActivateHelpPage`, `ExecuteServices`, `Proxy*`, `TwoFactorAuthEnabled`, `TwoFactorAuthType`, `RadiusServer*`, `MailTwoFactorAuth*`, `TwoFactorValidDurationInDays`, `SecretKey`; (b) die Datenbanktabellen `ApplicationSettings` und `Stammdat`. Startparameter (Adresse, Zertifikat, Datenbankverbindung, Authentifizierungsverfahren, Dienstausführung) liegen in der Datei, fachliche Einstellungen in der Datenbank. Für Docker wird die Datei als Volume eingebunden.
Aussage: Das System soll startrelevante und sicherheitsrelevante Parameter in einer Konfigurationsdatei und alle fachlichen Einstellungen in der Datenbank führen, sodass die Datenbank ohne Dateizugriff fachlich konfigurierbar bleibt.
Ergebnis: Ein Wechsel des Authentifizierungsverfahrens auf Systemebene erfordert eine Dateiänderung und einen Neustart; eine fachliche Einstellungsänderung wirkt ohne Neustart.
Belege:
- [PRIMÄR] docker/compose/WebServiceConfig.xml (vollständige Feldliste) - Begründung: Belegt Inhalt und Umfang der Dateikonfiguration.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:36 (`WebServiceConfigHelper.Current.ActiveDirectoryAuthEnabled`) und TwoFactorAuthBL.cs:41, 103, 185 - Begründung: Belegt die Auswertung der Dateikonfiguration im Sicherheitspfad.
- [PRIMÄR] docker/compose/compose.yaml (`volumes: - ./WebServiceConfig.xml:/app/WebServiceConfig.xml`) - Begründung: Belegt die Einbindung der Datei im Containerbetrieb.
- [PRIMÄR] src/webservice/c-entron.misc.ConnectionManager/ - Begründung: Belegt das Werkzeug zur Erzeugung der Datei.
Prüfidee: Eine Änderung an `TwoFactorAuthEnabled` wirkt erst nach Neustart; eine Änderung an `IsZugferdInvoiceActive` wirkt sofort.
Tracelinks: SyRS-040, SyRS-041, SyRS-049; StRS-019, StRS-024
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-035
Titel: Zentrale Build- und Versionierungsvorgaben
Ebene: SwRS
Typ: nicht-funktional (Wartbarkeit – Modifizierbarkeit)
Akteur: Build-Prozess
Vorbedingung: –
Fakt: `Directory.Build.props` setzt für alle Projekte gemeinsam: eingebettete Debugsymbole (`DebugType = embedded`), `TreatWarningsAsErrors = true` mit zentraler Ausnahmeliste, Herstellerangaben (`Company = NEXOWARE Systems GmbH`, `Product = NEXOWARE c-entron ERP`, `Copyright … 2012 - 2026`), einen Platzhalter für die Git-Commit-Kennung in `InformationalVersion` und die Kennzeichnung von Entwicklerbuilds (`IsDevBuild` → Präfix „Dev-Build", Definition `DEV_BUILD`). Die DevExpress-Version wird zentral über `DevExpress.Version.props` gesetzt und mit `src/nexus/Directory.Build.props` geteilt. `global.json` legt das .NET-SDK auf `10.0.100` mit `rollForward: latestFeature` fest. `version.json` (Nerdbank.GitVersioning) definiert die Version `2.0.2611-alpha`, Release-Zweige nach dem Muster `release/v{version}` und `versionIncrement: build`.
Aussage: Das System soll Übersetzungs-, Versionierungs- und Abhängigkeitsvorgaben zentral und für alle Projekte gemeinsam festlegen und Produktivbauten von Entwicklerbauten in der Versionsangabe unterscheidbar machen.
Ergebnis: Jede erzeugte Assembly trägt Herstellerangabe, Version, Git-Commit-Kennung und – bei Entwicklerbauten – eine entsprechende Kennzeichnung.
Belege:
- [PRIMÄR] Directory.Build.props:1-50 (alle genannten Eigenschaften) - Begründung: Zentrale, für alle Projekte wirksame Vorgabe.
- [PRIMÄR] global.json (SDK 10.0.100) - Begründung: Bindet den Build an eine definierte SDK-Version.
- [PRIMÄR] version.json (Nerdbank.GitVersioning, `2.0.2611-alpha`, Release-Zweigmuster) - Begründung: Belegt die automatisierte, git-basierte Versionsvergabe.
- [PRIMÄR] DevExpress.Version.props - Begründung: Belegt die zentrale Steuerung der Fremdkomponentenversion.
- [KONTEXT] docs/operations/build-server-and-automated-builds.md, docs/operations/update-devexpress.md, docs/operations/release-stop.md - Begründung: Beschreiben Buildbetrieb, Fremdkomponenten-Aktualisierung und Release-Prozess.
Prüfidee: Eine lokal erzeugte Assembly trägt in `InformationalVersion` das Präfix „Dev-Build"; eine Build-Server-Assembly trägt stattdessen die Commit-Kennung.
Tracelinks: SyRS-043, SyRS-044; StRS-019
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-036
Titel: MVVM-Struktur des Windows-Fachclients
Ebene: SwRS
Typ: funktional
Akteur: Windows-Fachclient
Vorbedingung: –
Fakt: Der Client umfasst 1 233 XAML-Dateien. Die Struktur trennt `Views/`, `ViewModels/`, `Modules/`, `Dialogs/`, `Wizards/`, `Behaviors/`, `Converters/` (in `Centron.Controls`), `Managers/`, `Services/`, `Style/`, `Resources/`, `Localization/`. Wiederverwendbare Oberflächenbausteine liegen in `Centron.Controls` (u. a. `PositionGrid`, `Checklist`, `FileViewer`, `PdfScanning`, `ProductMatrix`, `TaskManagement`, `Telephony`, `Wizard`, `ExcelExport`, `MailTemplates`). Das Basisframework `Centron.WPF.UI.Extension` stellt `Mvvm/`, `Commands/`, `Behaviors/`, `ValueConverter/`, `Extensibility/`, `Messages/`, `UiProperties/` bereit. Oberflächenbindungen nutzen `ObservableCollection<T>`, `INotifyPropertyChanged` und `DelegateCommand`. Dialoge laufen über `CentronApplication.Instance.DialogManager` (`ShowInputDialog`, `ShowConfirmationDialog`, `ShowDialog`).
Aussage: Das System soll die Oberfläche des Fachclients nach dem MVVM-Muster mit zentralem Dialogdienst, wiederverwendbaren Steuerelementen und einem gemeinsamen Basisframework aufbauen; Fachlogik soll nicht in Ansichten oder Code-Behind liegen.
Ergebnis: Eine Ansicht enthält ausschließlich Darstellungs- und Bindungsangaben; Fachentscheidungen liegen im ViewModel oder in der Fachlogikschicht.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/ (Ordner `Views`, `ViewModels`, `Modules`, `Dialogs`, `Wizards`, `Behaviors`, `Managers`, `Services`, `Style`, `Localization`) und src/centron/Centron.WPF.UI.Extension/Mvvm/, Commands/ - Begründung: Belegt die Strukturtrennung unmittelbar.
- [PRIMÄR] src/shared/Centron.Controls/ (36 fachliche Steuerelementbereiche) - Begründung: Belegt die Wiederverwendung von Oberflächenbausteinen zwischen Anwendungen.
- [KONTEXT] docs/reference/architecture/mvvm-in-centron.md, docs/guides/ui/create-module.md, create-dialog.md, create-settings-page.md - Begründung: Beschreiben Muster und Vorgehen für neue Ansichten, Module und Dialoge.
- [KONTEXT] docs/features/automatic-helpdesk-creation-templates.md:194-225, 521-546 (ViewModel-Aufbau, Dialogdienstverwendung) - Begründung: Konkretes Umsetzungsbeispiel des Musters.
Prüfidee: Stichprobe von 10 Ansichten: keine enthält Datenbank- oder Fachlogikzugriffe im Code-Behind; alle Aktionen laufen über `DelegateCommand`.
Tracelinks: SyRS-032; StRS-001, StRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-037
Titel: Telemetrieerhebung und -übertragung
Ebene: SwRS
Typ: Daten
Akteur: Web-Service
Vorbedingung: –
Fakt: Es existieren der Fachbereich `src/backend/Centron.BL/Telemetry/` (12 Entitätsdateien unter `Centron.Entities/Entities/Telemetry`, u. a. `TelemetryLicenseKind`) sowie die Hintergrunddienste `TelemetryFlushService` (Intervall 1 Minute) und `TelemetryUploadService` (12 KB) und `FlushAnalyticEventsService`. `LicenseGuids.cs` trägt den Klassenkommentar „Task: Update TelemetryLicenseKind.cs (in Centron.Data.Entities.Telemetry namespace) enum, when new licenses were added.", was die Kopplung von Telemetrie und Lizenzbestand belegt.
Aussage: [HYPOTHESE] Das System soll Nutzungs- und Betriebsdaten erheben und an den Hersteller übertragen; Art, Umfang, Rechtsgrundlage und Abschaltbarkeit dieser Übertragung sind festzulegen und gegenüber dem Anwenderunternehmen transparent zu machen.
Ergebnis: Der Anwender kennt Umfang und Zweck der übertragenen Daten und kann die Übertragung steuern.
Belege:
- [PRIMÄR] src/webservice/Centron.Host/AspNetCore/HostedServices/TelemetryUploadService.cs (12 KB), TelemetryFlushService.cs, FlushAnalyticEventsService.cs - Begründung: Belegt Erhebung und Übertragung als aktive Systemfunktion.
- [PRIMÄR] src/backend/Centron.BL/Telemetry/ und src/backend/Centron.Entities/Entities/Telemetry/ (12 Dateien) - Begründung: Belegt das Telemetriedatenmodell.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs:7 (Klassenkommentar zur Pflege von `TelemetryLicenseKind`) - Begründung: Belegt die Kopplung an den Lizenzbestand.
Prüfidee: Auswertung des Datenumfangs von `TelemetryUploadService` und Abgleich mit der Datenschutzerklärung gegenüber dem Anwenderunternehmen.
Tracelinks: SyRS-035; StRS-013, StRS-025
Konsolidierung: nein
Status: HYPOTHESE
Fehlende Information: Der Inhalt der übertragenen Telemetriedaten wurde in dieser Iteration nicht ausgelesen (`TelemetryUploadService.cs` und die zwölf Telemetrieentitäten wurden nicht im Detail analysiert). Ohne diese Analyse lässt sich weder der Personenbezug noch die Abschaltbarkeit beurteilen. Nachschlag in einer Folge-Iteration erforderlich; siehe `Analysebericht.md`.
```
```
ID: SwRS-038
Titel: Zwischenspeicherung häufig gelesener Stammdaten
Ebene: SwRS
Typ: nicht-funktional (Performance-Effizienz)
Akteur: Backend
Vorbedingung: –
Fakt: Es existiert die Komponente `CachedTableBL` (100 KB) sowie der Hintergrunddienst `CacheUpdateService`, der eine optimierte Aktualisierung frühestens alle 60 Sekunden ausführt (`if (_lastOptimizedUpdate == null || DateTime.Now - _lastOptimizedUpdate > TimeSpan.FromMinutes(1))`). Ergänzend nutzen einzelne Komponenten den sitzungsgebundenen Zwischenspeicher `Session.Advanced.Cache.GetOrAdd(schlüssel, factory)`, belegt für Benutzerrechte (`AllRightsFromAppUser{I3D}`), Web-Account-Rechte, das ZUGFeRD-Format (`GetZugferdFormatInternal{…}`) und Kunden-Konzernzuordnungen (`GetCompanyGroupCustomerI3DForReceiptData_{I3D}`). Im Client existiert `CentronCache.Instance` mit Feldern wie `CurrentUserAppRights` und `CrmSettings`.
Aussage: Das System soll häufig gelesene Stammdaten und Rechteinformationen auf Server- und Clientseite zwischenspeichern, die Zwischenspeicher zeitgesteuert aktualisieren und je Sitzung eine konsistente Sicht liefern.
Ergebnis: Wiederholte Lesezugriffe auf Stammdaten und Rechte erzeugen innerhalb der Gültigkeitsdauer keinen zusätzlichen Datenbankzugriff.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Services/CachedTableBL.cs (100 KB) und src/webservice/Centron.Host/AspNetCore/HostedServices/CacheUpdateService.cs:30 - Begründung: Belegt serverseitige Zwischenspeicherung und deren Aktualisierungstakt.
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:646, 674 - Begründung: Belegt sitzungsgebundene Zwischenspeicherung von Rechten.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:87 und src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:7291 - Begründung: Belegt weitere Anwendungsfälle.
- [KONTEXT] docs/guides/development/check-userrights.md:12 (`CentronCache.Instance.CurrentUserAppRights`) - Begründung: Belegt den clientseitigen Rechtezwischenspeicher.
Prüfidee: Nach Entzug eines Rechts wirkt die Änderung im Client spätestens nach Neuanmeldung; serverseitig spätestens nach Ablauf der Sitzung.
Tracelinks: SyRS-012, SyRS-038; StRS-002
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-039
Titel: Umfang und Verteilung des persistenten Datenmodells
Ebene: SwRS
Typ: Daten
Akteur: Persistenzschicht
Vorbedingung: –
Fakt: Das Datenmodell umfasst 1 179 Entitätsdateien in `src/backend/Centron.Entities/Entities/` und 983 FluentNHibernate-Zuordnungsdateien in `src/backend/Centron.DAO/Mappings/`, deren Ordnerstruktur die Domänenstruktur der Entitäten spiegelt. Die größten Domänen sind Sales (327 Entitätsdateien), Warehousing (103), Administration (98), CustomerArea (89), Accounts (54), DbEntities (39, temporäre Legacy-Entitäten), Statistics (35). Die NHibernate-Konfiguration liegt unter `Centron.DAO/NHibernateConfiguration/`, benutzerdefinierte Typen unter `UserTypes/`, benannte Abfragen unter `NamedQueries/`, Repositories unter `Repositories/`. Verwendete Fassung: NHibernate 5.6.0.
Aussage: Das System soll für jede persistierte Entität eine eigene, explizite Zuordnungsklasse führen, die in derselben Domänenstruktur wie die Entität abgelegt ist.
Ergebnis: Zu jeder mit NHibernate persistierten Entität ist die Zuordnungsdatei über den Domänenpfad auffindbar.
Belege:
- [PRIMÄR] Auszählung: src/backend/Centron.Entities/Entities/ = 1 179 `.cs`, src/backend/Centron.DAO/Mappings/ = 983 `.cs` - Begründung: Quantifiziert Umfang und Zuordnungsgrad objektiv.
- [PRIMÄR] src/backend/Centron.DAO/Centron.DAO.csproj (`<PackageReference Include="NHibernate" Version="5.6.0" />`) - Begründung: Belegt die eingesetzte Persistenzfassung.
- [PRIMÄR] src/backend/Centron.DAO/ (Unterordner `Mappings`, `NHibernateConfiguration`, `UserTypes`, `NamedQueries`, `Repositories`, `AdoNETDataAccess`, `CustomDAOs`) - Begründung: Belegt die Binnenstruktur der Persistenzschicht.
- [KONTEXT] docs/getting-started/ai-codebase-navigation.md:35-36 - Begründung: Bestätigt die Spiegelung der Domänenstruktur.
Prüfidee: Für eine Stichprobe von 20 Entitäten existiert im entsprechenden Unterordner von `Mappings/` eine Zuordnungsklasse `{Entität}Maps`.
Tracelinks: SyRS-039; StRS-001, StRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: SwRS-040
Titel: Getrenntes Rechtemodell für Portalkonten
Ebene: SwRS
Typ: Sicherheit
Akteur: Komponente `AppRightsBL` / `WebAccount`
Vorbedingung: Ein Portalkonto führt eine Aktion aus.
Fakt: Portalkonten (`WebAccount`) besitzen ein vom Mitarbeiterrechtemodell vollständig getrenntes Rechtemodell: Die Rechte liegen in der Tabelle `WebAccountsRights` (Spalten `WebAccountsI3D`, `WebRightsI3D`) und werden über `AppRightsBL.CheckWebRightsFromUser` bzw. `HasWebAccountRight` aufgelöst. Die Rechtekonstanten liegen in der Aufzählung `WebAccountRightsConst` (belegt: `WEBRIGHT_CREATEREQUEST`, `WEBRIGHT_EDITALLREQUESTS`). Es existiert keine Gruppenzwischenstufe – Rechte werden dem Konto direkt zugeordnet. Die Fachlogik verzweigt über `LoggedInUser.IsWebAccountLogin` (`HelpdeskBL.CheckRights`, `ReceiptBL.CanUserViewReceipt`). Die Verwaltung erfolgt über das Recht `WEBACCOUNT_MANAGEMENT = 20800162`; die Portalsichtbarkeit steuert zusätzlich `WebRightsVisibility`.
Aussage: Das System soll für externe Portalkonten ein eigenes, direkt kontobezogenes Rechtemodell führen, das vom Mitarbeiterrechtemodell getrennt ist, sodass interne Rechte niemals über ein Portalkonto wirksam werden können.
Ergebnis: Ein Portalkonto kann kein Mitarbeiterrecht besitzen; Fachfunktionen prüfen anhand von `IsWebAccountLogin`, welches Rechtemodell anzuwenden ist.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:113-130, 666-691 (`CheckWebRightsFromUser`, `HasWebAccountRight`, SQL über `WebAccountsRights`) - Begründung: Belegt das getrennte Datenmodell und dessen Auflösung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:410-415, 468-479 (Verzweigung über `IsWebAccountLogin`, `WebAccountRightsConst`) - Begründung: Belegt die Trennung in der Fachlogik.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs:10297-10302 (harte Ablehnung für Web-Benutzer) - Begründung: Belegt die Abschottung des internen Belegwesens.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/WebRightsVisibility.cs - Begründung: Belegt eine eigene Komponente für die Portalsichtbarkeit.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs:2391-2394 (`WEBACCOUNT_MANAGEMENT`) - Begründung: Belegt die Verwaltung der Portalkonten als eigenes Mitarbeiterrecht.
Prüfidee: Ein Portalkonto kann über keine Konfiguration ein Recht aus `UserRightsConst` erhalten; der Versuch, über die Portalanmeldung einen Beleg abzurufen, wird abgelehnt.
Tracelinks: SyRS-006, SyRS-026; StRS-002, StRS-011
Konsolidierung: Kandidat: Zwei getrennte Rechtemodelle (gruppenbasiert für Mitarbeiter, direkt für Portalkonten) und zwei getrennte Kennwortprüfungen (SwRS-026); im Zielsystem als ein Identitäts- und Autorisierungsdienst mit Mandantentrennung zusammenführbar.
Status: belegt
```
@@ -0,0 +1,160 @@
# Traceability-Matrix
**System:** NEXOWARE c-entron ERP · **Commit:** `79c1142f48` · **Erstellt:** 2026-08-25
**Umfang:** 114 Anforderungen (25 StRS, 49 SyRS, 40 SwRS), 421 Artefaktbelege (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`)
Die Spalte **Artefaktbeleg** nennt je Zeile den `PRIMÄR`-Beleg mit der höchsten Aussagekraft für die Anforderungskette. Die vollständigen Belege stehen in `StRS.md`, `SyRS.md` und `SwRS.md`. Beide Matrizen wurden maschinell aus den `Tracelinks`-Feldern der drei Spezifikationsdateien erzeugt.
---
## 1. Konsolidierte Matrix (StRS über SyRS zu SwRS)
Eine Zeile je SyRS-Anforderung. Die StRS-Spalte enthält alle Stakeholder-Anforderungen, die diese Systemanforderung begründen; die SwRS-Spalte alle Softwareanforderungen, die sie umsetzen.
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg |
|---|---|---|---|
| StRS-022 | SyRS-001 Auswahl Authentifizierungsverfahren | SwRS-025 | `src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs:54-146` |
| StRS-022 | SyRS-002 Rückfallverfahren abweichender Auth-Art | SwRS-025 | `Auth/AuthenticatorFactory.cs:57-86, 203-207` (`AppUser.AuthentificationKind`) |
| StRS-002, StRS-022 | SyRS-003 Sperrprüfung Benutzerkonto | SwRS-025, SwRS-026 | `Auth/Authenticator.cs:157-218` (`ValidateAppUser`) |
| StRS-022 | SyRS-004 Sitzungsticket mit Gültigkeitsdauer | SwRS-026 | `Administration/Logins/TicketBL.cs:26-28, 136-170` |
| StRS-004, StRS-022 | SyRS-005 Wiederverwendung Sitzungstickets | SwRS-005 | `Auth/Authenticator.cs:124-140` |
| StRS-002, StRS-004 | SyRS-006 Anmeldeverbot/-voraussetzung je Anwendungsart | SwRS-005, SwRS-025, SwRS-040 | `Auth/Authenticator.cs:68-86`; `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| StRS-004 | SyRS-007 Lizenzprüfung Version/Nutzungsobergrenze | SwRS-005 | `Administration/Licensing/LicenseManager.cs:258-302` |
| StRS-004, StRS-019 | SyRS-008 Betrieb ohne Lizenzserververbindung | SwRS-005 | `LicenseManager.cs:47-68, 117-139` (`FileLicenseCache`, `FakeOfficeClient`) |
| StRS-002, StRS-017 | SyRS-009 Rechteprüfung moderne REST-Schnittstelle | SwRS-002 | `Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs:29-56` |
| StRS-002, StRS-023 | SyRS-010 Authentifizierungspflicht Legacy-REST | SwRS-027, SwRS-030 | `Centron.WebServices.Core/Interception/Interceptors/AuthenticateAttribute.cs`; Auszählung 2 599 / 2 374 |
| StRS-002, StRS-023 | **SyRS-011 [HYPOTHESE]** 221 nicht attributierte Endpunkte | SwRS-030 | `Centron.Host/Services/ICentronRestService.cs` (`DeleteLogo`, `SaveCustomerSpecialArticle` ohne `[Authenticate]`) |
| StRS-002 | SyRS-012 Rechteprüfung mit Zwischenspeicherung | SwRS-003, SwRS-031, SwRS-038 | `Administration/Rights/AppRightsBL.cs:644-664` |
| StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 | SyRS-013 Einschränkende Rechte als Sichtbarkeitsfilter | SwRS-003, SwRS-020, SwRS-021 | `Sales/Support/HelpdeskBL.cs:269-291` (`ShowHelpdeskRight`) |
| StRS-002 | SyRS-014 Schutz der Administratorgruppe | SwRS-002, SwRS-003 | `AppRightsBL.cs:348-374, 714-759` |
| StRS-001, StRS-004 | SyRS-015 Modulsichtbarkeit als Recht UND Lizenz | SwRS-005 | `Centron.WPF.UI/Modules/ModuleRegistration.cs:421-448` |
| StRS-005, StRS-014 | SyRS-016 Belegzustandsmodell (drei Zustände) | SwRS-004, SwRS-006 | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs:6-28` |
| StRS-005, StRS-014, StRS-015 | SyRS-017 Validierung beim Speichern eines Belegs | SwRS-006, SwRS-007, SwRS-008, SwRS-009, SwRS-010, SwRS-013, SwRS-019, SwRS-031 | `Sales/Receipts/ReceiptBL.cs:3544-3868` |
| StRS-003, StRS-005 | SyRS-018 Belegnummernvergabe filialbezogen | SwRS-007, SwRS-009, SwRS-014, SwRS-032 | `Administration/Company/NumberGroupBL.cs:62-134` |
| StRS-005, StRS-014 | SyRS-019 Belegsperre bei gleichzeitiger Bearbeitung | SwRS-006 | `ReceiptBL.cs:3085-3096, 3160-3175` |
| StRS-005, StRS-008, StRS-014 | SyRS-020 Sperre Rückversionierung (Seriennr./Weiterverarbeitung) | SwRS-006 | `ReceiptBL.cs:3103-3115` |
| StRS-002, StRS-005, StRS-015 | SyRS-021 Mindestpreisprüfung mit Zweitanmeldung | SwRS-009, SwRS-013, SwRS-019 | `ReceiptBL.cs:9036-9124` |
| StRS-005 | SyRS-022 Beleg-Muster mit negativer Nummer | SwRS-006 | `Centron.Entities/.../ReceiptBase.cs:65`; `ReceiptBL.cs:3586-3593, 7280-7284` |
| StRS-005, StRS-006 | SyRS-023 Automatischer Belegabschluss | SwRS-006, SwRS-009 | `ReceiptBL.cs:9753-9763, 3815-3817` |
| StRS-005, StRS-010 | SyRS-024 Prüfung doppelter externer Nummern | SwRS-006 | `ReceiptBL.cs:3703, 3746` |
| StRS-002, StRS-008 | SyRS-025 Negative Lagerbuchung nur mit Recht | SwRS-009, SwRS-011, SwRS-013 | `Sales/Receipts/Internal/ReceiptArticleBookingBL.cs:347-405` |
| StRS-002, StRS-007, StRS-011 | SyRS-026 Rechteprüfung bei Tickets | SwRS-010, SwRS-011, SwRS-012, SwRS-040 | `Sales/Support/HelpdeskBL.cs:410-479` |
| StRS-007 | SyRS-027 Feldlängenbegrenzung Tickettexte | SwRS-010, SwRS-011 | `HelpdeskBL.cs:328-349` |
| StRS-013 | SyRS-028 DSGVO-Anonymisierung statt Löschung | SwRS-016 | `Administration/DataSecurity/DataSecurityBL.cs:787-789, 1195-1284` |
| StRS-006, StRS-021 | SyRS-029 Abbruch Vertragsrechnung ohne Nutzungsdaten | SwRS-009, SwRS-014 | `WebServices/.../AutomaticFacturaWebServiceBL.cs:721-726, 795-802, 2412` |
| StRS-012 | SyRS-030 Profilabhängige E-Rechnungserzeugung | SwRS-015 | `DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs:85-231` |
| StRS-001 | SyRS-031 Zwei parallele Server-Schnittstellen | SwRS-030 | `Centron.Host/Services/ICentronRestService*.cs` (2 599) gegenüber `Centron.Controllers/Controllers/` (160) |
| StRS-001, StRS-019 | SyRS-032 Dualer Client-Datenzugriff (BL/WS) | SwRS-001, SwRS-031, SwRS-036 | `Centron.WPF.UI/Services/Logics/**/{I,BL,WS}*Logic.cs` |
| StRS-001 | SyRS-033 Einheitliches Ergebnisobjekt `Result<T>` | SwRS-001, SwRS-031 | `Auth/Authenticator.cs:68-107`; `ReceiptBL.cs:3544-3868` |
| StRS-009, StRS-020, StRS-021 | SyRS-034 Externe Fachdienste in Integrationsbibliotheken | SwRS-015, SwRS-024 | `src/apis/` (7 Projekte); `Centron.Controllers/Controllers/v1/Integrations/` |
| StRS-025 | SyRS-035 Fehlertoleranter Hintergrundbetrieb | SwRS-023, SwRS-029, SwRS-037 | `Centron.Host/AspNetCore/HostedServices/ManagedBackgroundService.cs:32-157` |
| StRS-014, StRS-019 | SyRS-036 Ereignisprotokollierung (Schwelle, Rotation) | SwRS-032 | `CentronNexus.Host/appsettings.json` (Abschnitt `NLog`) |
| StRS-011, StRS-024 | SyRS-037 Begrenzung Dateiuploads Portal | SwRS-034 | `CentronNexus.Host/appsettings.json` (`Upload.Max*UploadSizeInMb`) |
| StRS-011, StRS-019 | SyRS-038 Begrenzung Ticket-Zwischenspeicher | SwRS-038 | `CentronNexus.Host/appsettings.json` (`TicketCache.CachedMonths` / `MaxClosedTickets`) |
| StRS-004, StRS-019 | SyRS-039 Automatische DB-Strukturaktualisierung | SwRS-018, SwRS-033, SwRS-039 | `Centron.BL/Administration/Scripts/ScriptMethods/Scripts/` (764 Skripte) |
| StRS-019 | SyRS-040 Verschlüsselte DB-Verbindungszeichenfolge | SwRS-023, SwRS-034 | `docker/compose/WebServiceConfig.xml` |
| StRS-019 | **SyRS-041 [HYPOTHESE]** Transportverschlüsselung (HTTPS) | SwRS-034 | `docker/compose/WebServiceConfig.xml`; `CentronNexus.Host/appsettings.json` (`Host.Url` = HTTP) |
| StRS-019 | **SyRS-042 [HYPOTHESE]** Schutz vor E-Mail-Versand in DEBUG-Builds | SwRS-035 | `docker/compose/compose.yaml` (Dienst `smtp` / Mailcatcher) |
| StRS-019 | SyRS-043 Warnungen als Fehler; Paketschwachstellen ausgenommen | SwRS-035 | `Directory.Build.props:11, 22-25` |
| StRS-005, StRS-014 | SyRS-044 Automatisierte Testabdeckung (12 Testprojekte) | SwRS-035 | `tests/` (12 Projekte, 378 `.cs`) |
| StRS-001, StRS-025 | SyRS-045 Volltextindizierung | SwRS-029 | `HostedServices/ObjectFulltextIndexUpdateService.cs:51`; `Centron.BL/IndexSearch/` |
| StRS-014 | SyRS-046 Feldgenaue Änderungsprotokollierung | SwRS-017 | `Centron.DAO/ChangeTracking/ChangeTrackingEventListener.cs:52-142` |
| StRS-002, StRS-014 | SyRS-047 Protokollierung Rechteänderungen | SwRS-002, SwRS-003 | `AppRightsBL.cs:762-857` (`AppRightLog`) |
| StRS-018 | SyRS-048 Deutsche Standardsprache, englische Zweitfassung | SwRS-022, SwRS-036 | `Centron.WPF.UI/Resources/LocalizedStrings.resx` (404 KB) / `.en.resx` (349 KB) |
| StRS-024 | SyRS-049 Zentrale typisierte Anwendungseinstellungen | SwRS-028, SwRS-034 | `Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs` (492 Einträge) |
---
## 2. Rückwärts-Traceability (SwRS über SyRS zu StRS)
Spalte **verknüpfte SyRS** enthält die Vereinigung aus Vorwärts- und Rückwärtsverweisen; Spalte **erreichbare StRS** die daraus über die SyRS-Ebene erreichbaren Stakeholder-Anforderungen.
| SwRS-ID | Titel | verknüpfte SyRS | erreichbare StRS |
|---|---|---|---|
| SwRS-001 | Sechsschichtige Anwendungsarchitektur | SyRS-032, SyRS-033 | StRS-001, StRS-019 |
| SwRS-002 | Datenmodell der Zugriffsberechtigungen | SyRS-009, SyRS-014, SyRS-047 | StRS-002, StRS-014, StRS-017 |
| SwRS-003 | Wiederherstellbare Standardrechtestruktur | SyRS-012, SyRS-013, SyRS-014, SyRS-047 | StRS-002, StRS-003, StRS-007, StRS-014, StRS-016, StRS-017 |
| SwRS-004 | Objektartschlüssel als systemweiter Verweismechanismus | SyRS-016 | StRS-005, StRS-014 |
| SwRS-005 | Lizenzkomponente als Singleton | SyRS-005, SyRS-006, SyRS-007, SyRS-008, SyRS-015 | StRS-001, StRS-002, StRS-004, StRS-011, StRS-019, StRS-022 |
| SwRS-006 | Vererbungsstruktur der Belegentitäten | SyRS-016, SyRS-017, SyRS-019, SyRS-020, SyRS-022, SyRS-023, SyRS-024 | StRS-005, StRS-006, StRS-008, StRS-010, StRS-014, StRS-015 |
| SwRS-007 | Zweigleisige Belegpersistenz | SyRS-017, SyRS-018 | StRS-003, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-008 | Versionstabellen als strukturgleiche Kopien | SyRS-017 | StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-009 | Delegation belegartspezifischer Logik | SyRS-017, SyRS-018, SyRS-021, SyRS-023, SyRS-025, SyRS-029 | StRS-002, StRS-003, StRS-005, StRS-006, StRS-008, StRS-014, StRS-015, StRS-021 |
| SwRS-010 | **[HYPOTHESE]** Reflexionsbasierte Auflösung | SyRS-017, SyRS-026, SyRS-027 | StRS-002, StRS-005, StRS-007, StRS-008, StRS-011, StRS-014, StRS-015 |
| SwRS-011 | Komponentenschnitt Ticketverarbeitung | SyRS-025, SyRS-026, SyRS-027 | StRS-002, StRS-007, StRS-008, StRS-011 |
| SwRS-012 | Konfigurierbare Ticketzustände | SyRS-026 | StRS-002, StRS-007, StRS-011 |
| SwRS-013 | Komponentenschnitt Belegpreis/-position | SyRS-017, SyRS-021, SyRS-025 | StRS-002, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-014 | Verteilung der Vertragsabrechnung | SyRS-018, SyRS-029 | StRS-003, StRS-005, StRS-006, StRS-021 |
| SwRS-015 | Kapselung E-Rechnungserzeugung | SyRS-030, SyRS-034 | StRS-009, StRS-010, StRS-012, StRS-020, StRS-021 |
| SwRS-016 | Anonymisierungskomponente mit Löschprotokoll | SyRS-028 | StRS-013 |
| SwRS-017 | Attributgesteuerte Änderungsprotokollierung | SyRS-046 | StRS-014 |
| SwRS-018 | Datenmodell- und Namenskonventionen | SyRS-039 | StRS-004, StRS-019 |
| SwRS-019 | Rechteabhängige Preisrücksetzung | SyRS-017, SyRS-021 | StRS-002, StRS-005, StRS-008, StRS-014, StRS-015 |
| SwRS-020 | Datenmodell Provisionsermittlung | SyRS-013 | StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 |
| SwRS-021 | Getrennte Auswertungskomponenten | SyRS-013 | StRS-002, StRS-003, StRS-007, StRS-016, StRS-017 |
| SwRS-022 | Lokalisierung je Assembly | SyRS-048 | StRS-018 |
| SwRS-023 | Drei Hostvarianten des Web-Service | SyRS-035, SyRS-040 | StRS-009, StRS-019, StRS-025 |
| SwRS-024 | Anbieterstruktur externe Artikelsuche | SyRS-034 | StRS-009, StRS-010, StRS-020, StRS-021 |
| SwRS-025 | Vererbungsstruktur der Authentifikatoren | SyRS-001, SyRS-002, SyRS-003, SyRS-006 | StRS-002, StRS-004, StRS-011, StRS-022 |
| SwRS-026 | **[HYPOTHESE]** Ablage/Prüfung Benutzerkennwörter | SyRS-003, SyRS-004 | StRS-002, StRS-022 |
| SwRS-027 | Portalkomponenten Dokumentensignatur | SyRS-010 | StRS-002, StRS-023 |
| SwRS-028 | Typisierter Einstellungszugriff | SyRS-049 | StRS-024 |
| SwRS-029 | Basisklasse aller Hintergrunddienste | SyRS-035, SyRS-045 | StRS-001, StRS-009, StRS-025 |
| SwRS-030 | Umschlagtypen Legacy-Schnittstelle | SyRS-010, SyRS-011, SyRS-031 | StRS-001, StRS-002, StRS-023 |
| SwRS-031 | Sitzungsfassade für Datenzugriff | SyRS-012, SyRS-017, SyRS-032, SyRS-033 | StRS-001, StRS-002, StRS-005, StRS-008, StRS-014, StRS-015, StRS-019 |
| SwRS-032 | Zeichenkettenverkettung in SQL (Nummernvergabe) | SyRS-018, SyRS-036 | StRS-003, StRS-005, StRS-014, StRS-019 |
| SwRS-033 | Skriptbasierte Schemafortschreibung | SyRS-039 | StRS-004, StRS-019 |
| SwRS-034 | Zweistufige Serverkonfiguration | SyRS-037, SyRS-040, SyRS-041, SyRS-049 | StRS-011, StRS-019, StRS-024 |
| SwRS-035 | Zentrale Build- und Versionierungsvorgaben | SyRS-042, SyRS-043, SyRS-044 | StRS-005, StRS-014, StRS-019 |
| SwRS-036 | MVVM-Struktur des Fachclients | SyRS-032, SyRS-048 | StRS-001, StRS-018, StRS-019 |
| SwRS-037 | **[HYPOTHESE]** Telemetrieerhebung | SyRS-035 | StRS-009, StRS-025 |
| SwRS-038 | Zwischenspeicherung Stammdaten | SyRS-012, SyRS-038 | StRS-002, StRS-011, StRS-019 |
| SwRS-039 | Umfang des persistenten Datenmodells | SyRS-039 | StRS-004, StRS-019 |
| SwRS-040 | Getrenntes Rechtemodell Portalkonten | SyRS-006, SyRS-026 | StRS-002, StRS-004, StRS-007, StRS-011 |
---
## 3. Abdeckungsübersicht
| Kennzahl | Wert |
|---|---|
| StRS-Anforderungen mit mindestens einem SyRS-Verweis | 25 von 25 (100 %) |
| SyRS-Anforderungen mit mindestens einem StRS-Verweis | 49 von 49 (100 %) |
| SyRS-Anforderungen mit mindestens einem SwRS-Verweis | 49 von 49 (100 %) |
| SwRS-Anforderungen mit mindestens einem SyRS-Verweis | 40 von 40 (100 %) |
| SwRS-Anforderungen mit direktem StRS-Verweis im eigenen Tracelinks-Feld | 40 von 40 (100 %) |
| Anforderungen ohne Artefaktbeleg | 0 |
| Anforderungen ohne `PRIMÄR`-Beleg | 0 |
| Tracelinks auf nicht existierende IDs | 0 |
| Mehrfach vergebene IDs | 0 |
| Als `[HYPOTHESE]` gekennzeichnet | 6 (SyRS-011, SyRS-041, SyRS-042, SwRS-010, SwRS-026, SwRS-037) |
| Mit Zusatz `Workaround` im Feld `Status` | 18 |
---
## 4. Hinweis zur Verweisrichtung
Die Verweise sind auf jeder Ebene vollständig: Jede Anforderung ist von beiden Nachbarebenen aus erreichbar. Sie sind jedoch nicht in jedem Einzelfall spiegelbildlich notiert – ein Verweis ist teils nur in der einen, teils nur in der anderen Anforderung geführt. Beide Matrizen oben lösen das auf, indem sie die Vereinigung aus Vorwärts- und Rückwärtsverweisen bilden. Für eine Folge-Iteration ist die vollständige Spiegelung aller Verweise in den Quelldokumenten vorgemerkt (siehe `Analysebericht.md`, Abschnitt „Nachschlag").
---
## 5. Konsolidierungskandidaten (Querschnitt)
Anforderungen, die im Feld `Konsolidierung` einen Kandidaten führen – also fachliche Redundanz markieren, die im Zielsystem zusammenzuführen ist:
| Thema | Beteiligte Anforderungen | Kernaussage |
|---|---|---|
| **Zwei REST-Schnittstellen** | SyRS-010, SyRS-031, SwRS-030 | 2 599 Legacy-Methoden neben 160 modernen Endpunkten; größter Einzelposten der Neuimplementierung |
| **Vierfache Belegpersistenz** | SwRS-007 | Legacy-Tabelle + moderne Sicht + temporäre Entität + Repository bilden dieselbe Struktur ab |
| **Zwei Einstellungsspeicher** | StRS-024, SyRS-049, SwRS-028 | `Stammdat` (728 Einträge) neben `ApplicationSettings` (492 Einträge) |
| **Zwei Identitäts-/Rechtemodelle** | SwRS-026, SwRS-040 | Mitarbeiter gruppenbasiert, Portalkonten direkt; zwei getrennte Kennwortprüfungen mit identischem Verfahren |
| **Autorisierung an drei Stellen** | SyRS-009 | Controller-Attribut, `Result`-Prüfung in `*WebServiceBL`, `HasUserRight` in `*BL` |
| **Einschränkende Rechte je Domäne** | StRS-003, SyRS-013 | „nur eigene" / „nur eigene Filiale" je Domäne eigenständig aufgelöst |
| **Belegartspezifische Rechtepaare** | SwRS-019 | Sieben Rechtepaare für Einkaufs-/Verkaufspreisänderung bilden dieselbe Regel ab |
| **Freigabe per Zweitanmeldung** | SyRS-021, SyRS-025 | Identisches Muster für Mindestpreis und negative Lagerbuchung |
| **46 Einzelprüfungen im Belegspeichern** | SyRS-017 | Als Regelkatalog je Belegart zusammenführbar |
| **EDI-Mapping je Distributor** | StRS-009 | Kopf-/Positions-Mapping siebenfach dupliziert |
| **Sieben Preisquellen** | StRS-020, SwRS-024 | Je eigene Abruf-, Auswertungs- und Anzeigelogik |
| **Drei Anonymisierungsroutinen** | StRS-013, SwRS-016 | Strukturgleiche Kontaktdaten, dreifach implementiert |
| **Sieben Ressourcenbestände** | SwRS-022 | Teilweise gleichlautende Texte |
| **Zwei Ticketzustandsmodelle** | SwRS-012 | Konfigurierbare Ticketzustände gegenüber fester `RequestStateEnum` |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 19 (Lauf M)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T19:59:55+02:00
- **Endzeit:** 2026-08-25T20:55:56+02:00
- **Dauer gesamt:** 00:56:01 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:55:60 (`duration_ms`) — API: 00:55:13
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-5070`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-26d8`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 247
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.191 Input-/19 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 162 |
| Output-Tokens | 268.834 (davon 21.146 Thinking-Tokens) |
| Cache-Write-Tokens | 578.094 |
| Cache-Read-Tokens | 24.008.783 |
| Agent-Turns | 177 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 162 | 4.191 | 4.353 |
| Output-Tokens | 268.834 | 19 | 268.853 |
| Cache-Write-Tokens | 578.094 | 0 | 578.094 |
| Cache-Read-Tokens | 24.008.783 | 0 | 24.008.783 |
| Tokens gesamt | 24.855.873 | 4.210 | **24.860.083** |
**Tokens gesamt: 24.860.083** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `cad89937-98ba-4a32-a943-eaa5ca8815c4`
- **Permission-Denials:** **1** – 1 x `PowerShell` - `New-Item -ItemType Directory` auf das eigene, bereits vorhandene `Ergebnisse\`-Verzeichnis; von `PowerShell(New-Item:*)` geblockt. Folgenlos, alle 7 Artefakte entstanden.
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 70.251 B | 25 Anforderungen |
| `SyRS.md` | 118.533 B | 49 Anforderungen |
| `SwRS.md` | 101.763 B | 40 Anforderungen |
| `Traceability.md` | 16.627 B | 51 Datenzeilen |
| `Hypothesen.md` | 14.857 B | 17 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 21.899 B | Domänenbegriffe |
| `Analysebericht.md` | 26.614 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **114 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,9 % |
| SyRS | 49 | 43,0 % |
| SwRS | 40 | 35,1 % |
| **Gesamt** | **114** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 38 | 33,3 % |
| Sicherheit | 29 | 25,4 % |
| Daten | 19 | 16,7 % |
| Schnittstelle | 10 | 8,8 % |
| nicht-funktional | 4 | 3,5 % |
| nicht-funktional (Performance-Effizienz) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit, ISO/IEC 25010: Fehlertoleranz) | 1 | 0,9 % |
| nicht-funktional (Zuverlässigkeit – Fehlertoleranz, Wiederherstellbarkeit) | 1 | 0,9 % |
| nicht-funktional (Wartbarkeit – Analysierbarkeit) | 1 | 0,9 % |
| nicht-funktional (Sicherheit – Ressourcenschutz) | 1 | 0,9 % |
| (8 weitere) | 8 | 7,0 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 421 |
| davon `PRIMÄR` | 314 (74,6 %) |
| davon `SEKUNDÄR` | 35 (8,3 %) |
| davon `KONTEXT` | 72 (17,1 %) |
| Belege je Anforderung (Median) | 4,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 114 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 94,7 % |
| als `HYPOTHESE` gekennzeichnet | 6 | 5,3 % |
| als Workaround vermerkt | 18 | 15,8 % |
| Konsolidierungskandidaten | 23 | 20,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (50 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 114 von 114 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(247 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":3312937,"num_turns":177,"stop_reason":"end_turn","session_id":"cad89937-98ba-4a32-a943-eaa5ca8815c4","total_cost_usd":24.5112775,"usage":{"input_tokens":162,"cache_creation_input_tokens":578094,"cache_read_input_tokens":24008783,"output_tokens":268834,"output_tokens_details":{"thinking_tokens":21146},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":578094,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1182,"cache_read_input_tokens":598251,"cache_creation_input_tokens":779,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":779},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4191,"outputTokens":19,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004286,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":162,"outputTokens":268834,"cacheReadInputTokens":24008783,"cacheCreationInputTokens":578094,"webSearchRequests":0,"costUSD":24.5069915,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[{"tool_name":"PowerShell","tool_use_id":"toolu_01VHU1qpzzX7x2TL9ovp6x6Y","tool_input":{"command":"$out=\"c:\\DEV\\MasterArbeit\\Versuche\\Versuch_01\\01_Lauf_2026-08-25_195916_opus5_solo_v3.6.0-5070\\Ergebnisse\"; New-Item -ItemType Directory -Force -Path $out | Out-Null; Test-Path $out","description":"Create output directory"}}],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Alle sieben Ergebnisdateien liegen im vorgegebenen Ausgabeverzeichnis; die Codebasis ist unverändert (`git status` leer, HEAD `79c1142f48`).\n\n## Ergebnis\n\n**114 Anforderungen** (25 StRS, 49 SyRS, 40 SwRS) mit **421 Artefaktbelegen** (314 `PRIMÄR`, 35 `SEKUNDÄR`, 72 `KONTEXT`), 362 KB Spezifikation.\n\n**Konsistenzcheck (maschinell, dokumentiert in `Analysebericht.md` §4):**\n- keine doppelten IDs, keine Tracelinks auf nicht existierende IDs\n- 0 Anforderungen ohne Beleg, 0 ohne `PRIMÄR`-Beleg — die verschärfte Evidenzpflicht für Sicherheit/Abrechnung/Berechtigungen ist damit durchgängig erfüllt\n- Vor-/Rückwärts-Traceability auf allen drei Ebenen zu 100 % geschlossen\n- Sieben im Verlauf gefundene Tracelink-Fehler sind korrigiert und in §4.1 offengelegt\n\n**Drei Befunde am laufenden System**, unabhängig von der Neuimplementierung:\n1. **221 von 2 599 Legacy-REST-Methoden ohne `[Authenticate]`** — darunter schreibende Operationen (`DeleteLogo`, `SaveCustomerSpecialArticle`, `DeleteContractExternalArticleImportHead`). Als Hypothese H-01 markiert, weil ein impliziter Schutz durch die WCF-Bridge statisch nicht ausschließbar war.\n2. **Ungesalzenes SHA-1 für Mitarbeiter- und Portalkennwörter**, Kennwort als Teil der SQL-Abfrage. Ist-Zustand durch `PRIMÄR`-Belege eindeutig; im Code steht `// TODO the password should be salted!!!`.\n3. **`NU1901`–`NU1904` (bekannte Paketschwachstellen) sind bewusst von `TreatWarningsAsErrors` ausgenommen.**\n\n**Wo die Spezifikation schwach ist** (§5.4, offengelegt statt kaschiert): 22 Anforderungen haben mindestens so viele `SEKUNDÄR`/`KONTEXT`- wie `PRIMÄR`-Belege — systematisch dort, wo `docs/` eine fertige Architekturbeschreibung lieferte und deshalb die Codeverifikation zurückgestellt wurde. Am schwächsten belegt ist ausgerechnet **SwRS-007 (zweigleisige Belegpersistenz)**, die aufwendigste Struktur der Belegverarbeitung.\n\n**Nicht abgedeckt:** KI-Bereich, Produktion/PLM, Passwort-Manager, TAPI, MyDay/TaskManager/Kalender, SelfCare (137 KB). Von `ReceiptBL.cs` (609 KB) wurden ~9 % gelesen — 39 der 46 Belegprüfungen sind namentlich erfasst, aber inhaltlich offen. Das ist der Nachschlag mit dem höchsten erwarteten Ertrag (Rang 1 in §7).","ttft_ms":3358,"ttft_stream_ms":1188,"time_to_request_ms":37,"type":"result","duration_ms":3359594,"uuid":"c879d5f1-e3f1-4b1e-a910-6486bd2333c8","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 25 | 21,9 % |
| SyRS | 49 | 43,0 % |
| SwRS | 40 | 35,1 % |
| **Gesamt** | **114** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 38 | 33,3 % |
| Sicherheit | 29 | 25,4 % |
| Daten | 19 | 16,7 % |
| Schnittstelle | 10 | 8,8 % |
| nicht-funktional | 4 | 3,5 % |
| nicht-funktional (Performance-Effizienz) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit, ISO/IEC 25010: Fehlertoleranz) | 1 | 0,9 % |
| nicht-funktional (Zuverlässigkeit – Fehlertoleranz, Wiederherstellbarkeit) | 1 | 0,9 % |
| nicht-funktional (Wartbarkeit – Analysierbarkeit) | 1 | 0,9 % |
| nicht-funktional (Sicherheit – Ressourcenschutz) | 1 | 0,9 % |
| (8 weitere) | 8 | 7,0 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 421 |
| davon `PRIMÄR` | 314 (74,6 %) |
| davon `SEKUNDÄR` | 35 (8,3 %) |
| davon `KONTEXT` | 72 (17,1 %) |
| Belege je Anforderung (Median) | 4,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 114 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 94,7 % |
| als `HYPOTHESE` gekennzeichnet | 6 | 5,3 % |
| als Workaround vermerkt | 18 | 15,8 % |
| Konsolidierungskandidaten | 23 | 20,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (50 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 114 von 114 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195916_opus5_solo_v3.6.0-5070\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:55:56.7541060+02:00
@@ -0,0 +1 @@
2026-08-25T19:59:55.6010375+02:00
@@ -0,0 +1,267 @@
# Analysebericht
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Analysestand:** Commit `79c1142f48` (Branch `main`), 2026-08-25
**Verfahren:** Reverse Requirements Engineering, Schritte 2–6 der Methodenkette; Schritt 1 (Scope) war vorgegeben, Schritt 7 (Validierung) erfolgt manuell durch Fachexperten.
**Werkzeuge:** ausschließlich lesender Dateizugriff, Textsuche und Auszählung im Arbeitsverzeichnis. Keine Ausführung der Anwendung, kein Datenbankzugriff, keine externen Quellen.
**Ergebnisdateien:** `StRS.md`, `SyRS.md`, `SwRS.md`, `Traceability.md`, `Hypothesen.md`, `Glossar.md`, dieser Bericht.
---
## 1. Untersuchungsgegenstand in Zahlen
Alle Zahlen wurden im Lauf durch Auszählen ermittelt.
| Kennzahl | Wert |
|---|---:|
| Größe des Arbeitsverzeichnisses (inkl. `.git`, `bin`, `obj`) | ca. 1,4 GB |
| C#-Quelldateien unter `src/` | 15.554 |
| XAML-Dateien unter `src/` | 1.233 |
| Razor-Komponenten unter `src/` | 491 |
| Eigenständige Projekte unter `src/` | 28 |
| NHibernate-Entitäten (`Centron.Entities/Entities/`) | 1.179 in 85 Domänenordnern |
| Datenbank-Migrationsklassen | 764 (höchste Nummer `ScriptMethod11820`) |
| Rechtekonstanten (`UserRightsConst`) | 751 auf 2.819 Zeilen |
| Web-Account-Rechte (`WebAccountRightsConst`) | 53 (davon 17 `[Obsolete]`) |
| Anwendungseinstellungen `ApplicationSettingID` | 491 (nächste freie Kennung 10471) |
| Anwendungseinstellungen `AppSettingsConst` (Altbestand) | 728 |
| Objektarten (`CentronObjectKindNumeric`) | über 250 (nächste .NET-Kennung 7600154) |
| Operationen der Alt-REST-Schnittstelle (`[WebInvoke]`) | 2.618 auf 32 Dateien |
| Endpunkte der modernen REST-Schnittstelle | 160 (71 GET, 57 POST, 20 PUT, 11 DELETE, 1 PATCH) in 30 Controllern |
| Registrierte Anwendungsmodule (WPF-Client) | 83 aktive Registrierungen in 15 Regionen (1 weitere auskommentiert) |
| Einstellungsseiten ohne Modulbezug | 82 fest plus 1 rechteabhängig; zusätzlich 8 persönliche Einstellungsseiten |
| Testdateien gesamt | 402 (E2E 314, Backend 45, APIs 15, Playwright 12, Shared 9, Integration 7) |
| Fachliche E2E-Testbereiche | ca. 130 |
| Entwicklerdokumentation unter `docs/` | 44 Dateien, ca. 8.500 Zeilen |
**Größte Einzelartefakte (Zeilen)**
| Datei | Zeilen | Rolle |
|---|---:|---|
| `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` | 11.441 | Kern der Belegverarbeitung |
| `src/webservice/Centron.Host/Services/ICentronRestService.cs` | 7.679 | Alt-Schnittstellenvertrag (Hauptdatei) |
| `src/backend/Centron.BL/Sales/Receipts/ReceiptItemBL.cs` | 4.290 | Positionsverarbeitung |
| `…/UserRightsConst.cs` | 2.819 | Rechteregister |
| `…/ICentronRestService.Receipts.cs` | 1.944 | Alt-Schnittstelle Belege |
| `…/ICentronRestService.Accounts.cs` | 1.741 | Alt-Schnittstelle Adressen |
| `…/BookKeepingExportBL.cs` | 1.610 | Buchhaltungsexport |
---
## 2. Modul- und Komponentenübersicht
### 2.1 Projektstruktur (Schicht → Projekt → Umfang)
| Schicht | Projekt | C#-Dateien | Rolle |
|---|---|---:|---|
| Client | `src/centron/Centron.WPF.UI` | 5.255 | WPF-Desktop-Client, Module, ViewModels, `ILogic`-Trippel |
| Client | `src/centron/Centron.WPF.UI.Extension` | 160 | Erweiterungen des Clients |
| Schnittstelle | `src/webservice/Centron.WebServices.Core` | 2.530 | DTOs, Alt-REST-Implementierung, Rechteregister |
| Backend | `src/backend/Centron.BL` | 2.068 | Geschäftslogik, Migrationsskripte, Web-Service-BL |
| Backend | `src/backend/Centron.Entities` | 1.185 | NHibernate-Entitäten, temporäre Legacy-Entitäten |
| Backend | `src/backend/Centron.DAO` | 1.131 | FluentNHibernate-Abbildungen, Sitzungen, benannte Abfragen |
| UI-Bibliothek | `src/shared/Centron.Controls` | 880 | Wiederverwendbare Steuerelemente |
| Backend | `src/backend/Centron.Interfaces` | 764 | Verträge, Enums, Einstellungskennungen |
| Portal | `src/nexus/CentronNexus` | 762 (+491 Razor) | Blazor-Server-Portal |
| Host | `src/webservice/Centron.Host` | 158 | Dienstkern, Alt-Schnittstellenvertrag |
| Integration | `src/backend/Centron.Gateway` | 105 | EDI-Parser-Assemblies |
| Sonstige | `src/shared/Centron.Core`, `src/backend/Centron.Common` | 74 / 58 | Querschnittshilfen |
| Externe APIs | `src/apis/*` (8 Projekte) | 237 | FinAPI, GLS, Shipcloud, ITscope, Icecat, COP, EGIS, eb-Interface |
| Schnittstelle | `src/webservice/Centron.Controllers` | 57 | Moderne REST-Controller |
| Hosts | `Centron.Host.Console`, `.WindowsService`, `CentronNexus.Host` | 4 / 5 / 9 | Startprojekte je Betriebsform |
| Add-In | `src/nexus/CentronNexus.OutlookAddIn` | 59 | Outlook-Integration |
| Werkzeug | `src/webservice/c-entron.misc.ConnectionManager` | 38 | Verbindungsverwaltung |
### 2.2 Fachliche Module (aus `ModuleRegistration.cs`, 15 Regionen, 83 aktive Registrierungen)
| Region | Module (Auswahl) |
|---|---|
| Abrechnung | Pauschalabrechnung, Provisionsauswertung, Provisionsschemas, Provisionsschema-Kundenzuordnung, Vereinfachte Ticketabrechnung, Vertragsabrechnung |
| Administration | Aufschläge Stundensätze, c-entron DSGVO, Einstellungen, Kontenrahmen, Leasing/Service, Mailvorlagen, Mandanten, Mitarbeiter, Rechteverwaltung, Textbausteine, Ticketprozess-Vorlagen, Vertragsarten |
| Adressen/CRM | Adressstamm, CRM (alternativ), Audit, CRM-Projekte, Kampagnen/Mailing, Lieferantenverträge, PLM, Stammblätter |
| Automatisierung | Erwartete Events, Erwartete-Events-Auswertung, Reportserver |
| Buchhaltung/Finanzen | Buchhaltungsexport/-import, Datev Belegtransfer, Kalkulation pro Filiale, Mahnung, OPOS, SEPA, Zahlungseingang |
| Controlling/Analytics | Analytics, Leistungsnachweise, Management Info, Mitarbeiterauslastung, MSP-Auswertung, MSP-Collector, MSP-Dashboard, Vertragsauswertung |
| Einkauf | Belegerfassung, Bestellvorschlagsliste, EDI-Verwaltung, Eingang/Kalkulation |
| Helpdesk | Checklisten, Projektverwaltung, RMA/Werkstatt, Taskmanagement, Ticket-Liste |
| Hilfe | c-entron Inspektor, c-entron Logs, SQL-Manager |
| Logistik | Artikelimport, Artikelverwaltung, Inventur, Kommissionierung |
| MyCentron | Dashboard, Mein Tag, Telefonate, Todo-Liste, AI-Chat |
| Passwort Manager (im Code als „obsolate“ markiert) | Richtlinienverwaltung, Zugänge, Zugangsbereiche |
| Produktion | Maschinenverwaltung, Produktionsaufträge |
| Stammdaten | Belegkonditionen, Data Updater, Kostenträger/-stellen, Länder, Mehrwertsteuer, Projektpreisimport, Reportverwaltung, Warengruppen |
| Verträge | Dynamischer/statischer Datenimport, Klick-Zählerverwaltung |
---
## 3. Analysetiefe je Bereich
Die Analysetiefe wurde risikobasiert priorisiert: zuerst die Bereiche mit hoher fachlicher Dichte (Belegverarbeitung, Verträge), anschließend die Bereiche mit erhöhten Evidenzanforderungen (Sicherheit, Berechtigungen, Fakturierung), danach Betrieb und Querschnitt, zuletzt Randbereiche.
**Legende:** **A** = Kernartefakte vollständig gelesen und Regeln aus dem Code abgeleitet · **B** = zentrale Artefakte gelesen, Umfang über Struktur- und Signaturanalyse erschlossen · **C** = nur strukturell erfasst (Verzeichnisse, Klassennamen, Registrierung, Dokumentation) · **D** = nicht analysiert
| Bereich | Tiefe | Was konkret gelesen wurde | Anforderungen |
|---|:--:|---|---|
| Belegkern (Zustand, Speicherung, Version, Prüfkette) | **A** | `ReceiptBase`, `ReceiptState`, `CentronObjectKindNumeric`, `ReceiptBL.SaveReceipt` (Zeilen 3495–3925), `IReceiptSpecificLogic` (vollständig), `AutomaticallyCloseReceiptHelperBL` (vollständig) | StRS-006 … 012, SyRS-020 … 026, SwRS-001 … 009 |
| Belegweiterverarbeitung | **A** | `CanBeForwardedFrom/Into` aller sieben Belegstrategien | StRS-007, SyRS-022, SwRS-005 |
| Rechnungsstorno und Vertragsbezug | **A** | `ReceiptInvoiceBL.CancelInvoice`, `IsLastContractInvoice`, `GetContractsFromInvoice` | StRS-009, SyRS-024/028, SwRS-006 |
| Authentifizierung, 2FA, Ticket, Token | **A** | `Authenticator`, `BasicAuthenticator`, `TwoFactorAuthBL`, `TicketBL`, `JwtAuthController`, `AccessTokenBL` | StRS-005, SyRS-001 … 011, SwRS-025/026/044/045/046 |
| Rechte und Autorisierung | **A** | `UserRightsConst` (Struktur), `AuthorizeUserRightAttribute`, `CentronAuthorization`, `CentronRights.md`, Rechteprüfungen in `ReceiptBL` | StRS-002/020, SyRS-005/006/010/036, SwRS-021/022 |
| Nummernkreise | **A** | `NumberGroupBL` (vollständig), `MandatoryBL.GetNumberGroup` | StRS-004, SyRS-014/015, SwRS-024/060 |
| Kreditlimit und Mindestpreis | **A** | `CheckIfCustomerLimitIsReached`, `CheckArticleMinPrices` (vollständig) | StRS-010/011, SyRS-025/026, SwRS-007 |
| Modul- und Lizenzregistrierung | **A** | `ModuleRegistration.cs` (vollständig, 954 Zeilen) | StRS-002/003, SyRS-004, SwRS-023/066/067 |
| Betriebskonfiguration und Protokollierung | **A** | `WebServiceConfig`, `appsettings.json`, `nlog.config` (Windows-Dienst), `Dockerfile`, `Directory.Build.props`, `global.json` | SyRS-063/065/066/070, SwRS-049/050/052/053 |
| Helpdesk (Pflichtfelder, Abschluss) | **B** | `HelpdeskBL.DoValidateMandatoryFields`, `HelpdeskCloseBL` (Zeilen 100–220), Verzeichnisinventar (47 Einträge) | StRS-019, SyRS-034/035, SwRS-016 |
| Zeiterfassung | **B** | `HelpdeskTimerBase`, Aufrufe von `ReceiptItemTimerBL` in `ReceiptBL` | StRS-021, SyRS-037, SwRS-018 |
| Verträge und Kontingente | **B** | `BillingIntervalKinds`, `BillingKinds`, `ContingentLimitKinds`, `ContractSpecificLogic` (Ausschnitte), `WriteReceiptLogs`, Entwicklerdokumentation | StRS-013/014, SyRS-027 … 029, SwRS-010/011 |
| Lager und Barcodes | **B** | `ReceiptArticleBookingBL` (Signaturen und Buchungspfad), Barcodeprüfungen in `ReceiptBL` | StRS-017/018, SyRS-032/033, SwRS-014/015 |
| Buchhaltungsexport | **B** | `BookKeepingExportBL` (Methodenverzeichnis, `IsReceiptExported`) | StRS-026, SyRS-039, SwRS-027 |
| E-Rechnung ZUGFeRD/XRechnung | **B** | `InvoiceZugferdBL` (Kopf und Formatkonstanten), `ZugferdFileKind`, Einstellungskennungen, zwei Referenzdokumente | StRS-027, SyRS-043, SwRS-028 |
| Portal (Nexus) | **B** | `CentronAuthorization` (vollständig), Verzeichnisinventar, `appsettings.json`, `WebAccountRightsConst` | StRS-023, SyRS-010/061/062/071, SwRS-020 |
| Warenkorb und Web-Angebot | **B** | `ReceiptCartBL` (öffentliche Schnittstelle), `ReceiptCartReleaseSystemBL` (Freigabepfad), `WebReceiptState` | StRS-024/025, SyRS-041/042 |
| Schnittstellen (alt und modern) | **B** | Dateiinventar und Auszählung beider Schnittstellen, `AuthorizeUserRightAttribute`, `KebabCaseTransformer` | SyRS-068/069, SwRS-054/055/056 |
| Datenbankmigration | **B** | `ScriptEngineBL` (vollständig), Skriptinventar, zwei Regeldokumente | StRS-042, SyRS-059, SwRS-043 |
| Mahnwesen, SEPA, Online-Banking | **C** | Klassen- und Modulinventar, Statuszuweisungen in `OnlineBankingAccountTransactionsBL` (Zeilen 928/1049), `BlockNewReceiptsDunningLevel` | StRS-028/029, SyRS-044/045, SwRS-029/030 |
| Provision | **C** | Entitäteninventar, Aufruf `SaveProvision`, Vertragsmitglieder, Testbereiche | StRS-030, SyRS-046, SwRS-031 |
| Artikel und Preisfindung | **C** | Klasseninventar `Warehousing/`, `ActionPrice`-Dokumentation, `CalculateReceiptItemPrices`-Aufruf | StRS-031, SyRS-047, SwRS-032 |
| EDI | **C** | Dateiinventar der partiellen Klassen, Gateway-Assemblies, zwei Referenzdokumente | StRS-016, SyRS-031, SwRS-013 |
| Externe APIs (ITscope, Icecat, GLS, Shipcloud, FinAPI) | **C** | Projektstruktur, Schnittstellendateien, Nutzungsstellen | StRS-032/033, SyRS-048/049, SwRS-033/034 |
| RMA, DSGVO, TAPI, Reporting, Projekte | **C** | Klasseninventar, Objektarten, Modul- und Einstellungsregistrierung, Nutzungsstellen in `ReceiptBL` | StRS-034 … 038, SyRS-050 … 054, SwRS-035 … 039 |
| Produktion, Inventur, Kommissionierung, MSP, Mailings, Kampagnen, Checklisten, Passwortmanager, MyDay, Kalender/Exchange, Chats, Videoportal, Umfragen, ITPlanner, DocuBoard, Telekom D!VE, Mass Update, Mail-Scanner | **D** | nicht analysiert (siehe Abschnitt 5) | keine |
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde automatisiert über die drei Spezifikationsdateien und `Traceability.md` ausgeführt (Auswertung der Feldstruktur `ID:` … `Status:` je Anforderungsblock).
| Prüfung | Ergebnis |
|---|---|
| Anzahl Anforderungsblöcke gesamt | **182** (StRS 42, SyRS 69, SwRS 71) |
| Doppelte oder mehrfach vergebene IDs | **keine** |
| Anforderungen ohne jeden Beleg | **keine** |
| Anforderungen ohne `PRIMÄR`-Beleg | **keine** — damit erfüllen auch alle Anforderungen der Risikoklassen Sicherheit (32), Fakturierung und Berechtigungen die verschärfte Evidenzvorgabe |
| Anforderungen ohne Prüfidee | **keine** |
| Tracelinks auf nicht existierende IDs | **keine** |
| In `Traceability.md` referenzierte, aber nicht existierende IDs | **keine** |
| Anforderungen, die in `Traceability.md` fehlen | **keine** |
| Lücken in den ID-Bereichen | vorhanden und in `Traceability.md`, Abschnitt 3, dokumentiert (SyRS: 012–013, 016–019, 074–079; SwRS: 059, 068–069). Ursache: thematische Nummernblöcke während der Formalisierung. Keine Auswirkung auf die Eindeutigkeit. |
**Belegverteilung**
| Ebene | Anforderungen | `PRIMÄR` | `SEKUNDÄR` | `KONTEXT` | Belege gesamt | Belege je Anforderung |
|---|---:|---:|---:|---:|---:|---:|
| StRS | 42 | 86 | 24 | 24 | 134 | 3,19 |
| SyRS | 69 | 127 | 24 | 25 | 176 | 2,55 |
| SwRS | 71 | 128 | 18 | 29 | 175 | 2,46 |
| **Summe** | **182** | **341 (70,3 %)** | **66 (13,6 %)** | **78 (16,1 %)** | **485** | **2,66** |
**Typverteilung**
| Typ | Anzahl |
|---|---:|
| funktional | 75 |
| Sicherheit | 32 |
| Daten | 24 |
| Schnittstelle | 23 |
| nicht-funktional (ISO/IEC 25010) | 28 |
Verteilung der nicht-funktionalen Anforderungen auf die Qualitätsmerkmale nach ISO/IEC 25010: Wartbarkeit 11, Übertragbarkeit 5, Zuverlässigkeit 4, Performance-Effizienz 3, Sicherheit 3, Usability 2. **Nicht abgedeckte Merkmale:** Funktionale Eignung (als eigenständiges NFR), Kompatibilität und Interaktionsfähigkeit sind nicht als nicht-funktionale Anforderungen ausgewiesen; Interoperabilität ist stattdessen über die 23 Schnittstellenanforderungen erfasst.
**Statusverteilung**
| Status | Anzahl |
|---|---:|
| `belegt` | 144 |
| `belegt; Workaround` | 31 |
| `HYPOTHESE` | 7 |
---
## 5. Bekannte Lücken
### 5.1 Nicht analysierte Fachbereiche (Tiefe D)
Für die folgenden Bereiche wurden **keine Anforderungen erhoben**. Sie sind im Code vorhanden und über Modulregistrierung, Objektarten und Entitätsordner nachweisbar, wurden aber im Rahmen der Priorisierung nicht geöffnet:
Produktion (Maschinen, Produktionsaufträge, Arbeitsschritte) · Inventur und Kommissionierung im Detail · MSP-Auswertung, MSP-Collector, MSP-Dashboard · Kampagnen und Mailings · Checklisten und Ticketprozessvorlagen · Passwortmanager (im Code als „obsolate“ markiert) · MyDay und Mitarbeiterauslastung · Kalender-, Exchange- und Microsoft-Graph-Synchronisation · Chats · Videoportal · Umfragen/Audit · ITPlanner · DocuBoard und Dokumentationsassistenten · Telekom D!VE · Mass Update / Data Updater · Mail-Scanner · Erwartete Events · Leasing/Service · Statistiken und Management Info · Outlook-Add-In · Asset-Management (über 100 Objektarten ab 7600000).
Der Umfang dieser Lücke ist erheblich: Die Asset-Management-Objektarten allein stellen den größten zusammenhängenden Block in `CentronObjectKindNumeric`.
### 5.2 Nicht lesbare oder nicht gelesene Artefakte
| Artefakt | Status | Auswirkung |
|---|---|---|
| Datenbankschema (DDL) | **nicht vorhanden** — im Arbeitsverzeichnis existieren keine `.sql`-Dateien (0 Treffer). Das Schema entsteht ausschließlich zur Laufzeit aus 764 Skriptmethoden. | Constraints, Indizes und Spaltentypen konnten nicht als eigenständige Belege herangezogen werden. Alle datenbezogenen Aussagen stützen sich auf Entitäten, Abbildungen und die Entwicklerdokumentation. |
| Produktivdaten | nicht verfügbar | Mengengerüste, tatsächliche Nutzung von Modulen und die Belegung von Konfigurationsfeldern sind unbekannt. |
| Klasse `DataQualityService` | nicht gelesen (nur Entwicklerdokumentation) | Die konkrete Aufgabenliste und die Löschfristen sind offen (Hypothese H-06). |
| Klasse `DeveloperSecurity` | nicht gelesen (nur Entwicklerdokumentation) | Die Aussagen zu SyRS-067/SwRS-053 stützen sich auf `KONTEXT`-Belege und die Buildkonfiguration. |
| `LicenseGuids.cs`, `ApplicationKind.cs` | nicht im Volltext gelesen | Umfang der Lizenzen und die Zuordnung erforderlicher/ausschließender Rechte je Anwendungsart sind nicht quantifiziert. |
| Startcode der Hosts (`Program.cs` / `Startup`) | nicht gelesen | Transportverschlüsselung, Middleware-Reihenfolge und Dienstregistrierung sind offen (Hypothese H-07). |
| `.github/workflows/*.yml`, `azure/*.yml` | nur als Dateiliste erfasst | Aussagen zur Prüfstrecke stützen sich auf Existenz und Benennung, nicht auf den Inhalt. |
| Commit-Historie | 30 jüngste Commits gelesen | Ältere Änderungsgründe und Ticketbezüge blieben unberücksichtigt. |
| Tickets, Release Notes, Migrationsnotizen | nicht als Datei vorhanden | Ticketnummern waren nur über Commit-Betreffzeilen als `KONTEXT` verwertbar. |
### 5.3 Methodische Einschränkungen
- **Statische Analyse ohne Ausführung:** Alle Aussagen zu Laufzeitverhalten (Zustandsübergänge, Reihenfolgen, Nebenläufigkeit) sind aus dem Quelltext abgeleitet, nicht beobachtet.
- **Reihenfolgeabhängigkeiten:** Der Speichervorgang eines Belegs enthält über 40 Prüf- und Aktualisierungsschritte, deren Reihenfolge fachlich bedeutsam ist, aber nur durch Kommentare abgesichert wird. Die Spezifikation hält die Reihenfolge fest (SwRS-008), kann sie aber ohne Ausführung nicht validieren.
- **Konfigurationsabhängiges Verhalten:** Zahlreiche Regeln greifen nur bei bestimmter Einstellungsbelegung (1.219 Einstellungswerte in zwei Registern). Welche Belegung beim Kunden vorliegt, ist unbekannt.
---
## 6. Selbstbewertung
### 6.1 Was wurde vollständig, was stichprobenhaft, was gar nicht analysiert?
**Vollständig (Tiefe A) — 9 Bereiche, ca. 60 Anforderungen.**
Belegkern, Belegweiterverarbeitung, Rechnungsstorno, Authentifizierung mit Zweitfaktor und Ticketverwaltung, Rechte und Autorisierung, Nummernkreise, Kreditlimit und Mindestpreis, Modul- und Lizenzregistrierung, Betriebskonfiguration. In diesen Bereichen wurden die tragenden Klassen im relevanten Umfang gelesen; die Regeln stammen unmittelbar aus durchgesetztem Code. Die Belegdichte liegt hier bei nahezu 100 % `PRIMÄR`.
**Stichprobenhaft (Tiefe B/C) — 15 Bereiche, ca. 115 Anforderungen.**
Helpdesk, Zeiterfassung, Verträge, Lager und Barcodes, Buchhaltungsexport, E-Rechnung, Portal, Warenkorb, Schnittstellen, Datenbankmigration (B); Mahnwesen, Zahlungsverkehr, Provision, Preisfindung, EDI, externe APIs, RMA, DSGVO, TAPI, Reporting, Projekte (C). Hier wurden Struktur, Signaturen, Enums und Aufrufstellen ausgewertet; die Anforderungen beschreiben verlässlich **dass** und **wo** eine Funktion existiert, bei Tiefe C jedoch nicht durchgängig **wie** sie im Detail rechnet.
**Gar nicht analysiert (Tiefe D) — ca. 20 Fachbereiche, 0 Anforderungen.**
Siehe Abschnitt 5.1. Die größte inhaltliche Lücke.
### 6.2 Wo ist der Beleg dünn?
Die Vorgabe „mindestens ein `PRIMÄR`-Beleg für Sicherheits-, Abrechnungs- und Berechtigungsanforderungen“ ist ausnahmslos erfüllt. Dünn ist die Belegbasis dennoch an folgenden Stellen:
| Stelle | Art der Schwäche | Betroffene IDs |
|---|---|---|
| Bereiche der Tiefe C | Der `PRIMÄR`-Beleg weist die **Existenz** einer Komponente nach, nicht ihre **Rechenregel**. Beispiel: Provision und Preisfindung sind als Komponenten belegt, die konkrete Berechnungsformel wurde nicht gelesen. | StRS-030/031, SyRS-046/047, SwRS-031/032 |
| Entwicklerschutz, Hintergrunddienst | Die tragende Klasse wurde nicht gelesen; die Aussage stützt sich überwiegend auf `KONTEXT`-Belege aus `docs/`. | SyRS-064/067, SwRS-051/053 |
| EDI-Detailregeln | Die distributorspezifischen Importregeln wurden nicht im Code verifiziert, sondern nur über Dateistruktur und Referenzdokument erfasst. | StRS-016, SyRS-031, SwRS-013 |
| ZUGFeRD-Feldzuordnung | Die Feldzuordnung stammt aus zwei Referenzdokumenten (`KONTEXT`), nicht aus dem Erzeugungscode. | StRS-027, SyRS-043 |
| Rechnungswesen (SEPA, OPOS, Mahnung) | Zustandsänderungen sind an einzelnen Zeilen belegt; der vollständige Ablauf des Mahnlaufs und der SEPA-Dateierzeugung wurde nicht gelesen. | StRS-028/029, SyRS-044/045 |
| Datenmodell-Aussagen allgemein | Ohne DDL im Arbeitsverzeichnis konnte kein Constraint als `PRIMÄR`-Beleg herangezogen werden; alle Datenaussagen stützen sich auf Entitäten und Abbildungen. | alle Anforderungen vom Typ `Daten` (24) |
Der `KONTEXT`-Anteil von 16,1 % ist höher als der `SEKUNDÄR`-Anteil (13,6 %) — ein direktes Ergebnis der ungewöhnlich umfangreichen Entwicklerdokumentation (44 Dateien, ca. 8.500 Zeilen) und der aussagekräftigen Codekommentare, die vielfach die Entstehungsgeschichte einer Regel erklären (z. B. „SKA 2023-01-03: Changed from IsZero to IsZeroOrNegative …“). Diese Belege wurden bewusst als `KONTEXT` und nie als alleinige Grundlage einer Anforderung verwendet.
### 6.3 Welche Erkenntnisse legen einen Nachschlag nahe?
**Vorrangig (Iteration 2):**
1. **Fachbereiche der Tiefe D öffnen.** Produktion, MSP, Kampagnen, Checklisten, Kalender-/Exchange-Synchronisation, Asset-Management. Empfehlung: je Bereich zuerst die Modulregistrierung, dann die zentrale `*BL`-Klasse und die zugehörigen Objektarten. Erwarteter Zuwachs: 40–60 Anforderungen.
2. **Sieben offene Hypothesen klären** (`Hypothesen.md`), vorrangig H-03 (Mandantentrennung), H-07 (Transportverschlüsselung) und H-05 (Verbindungszeichenfolge). H-03 ist architekturbestimmend für ein SaaS-Zielsystem und sollte vor jeder Zielarchitekturentscheidung beantwortet werden.
3. **Rechenregeln der Tiefe-C-Bereiche nachziehen:** Preisfindung (Vorrang der Preisquellen), Provisionsberechnung, Kontingentberechnung, Mahnstufenlogik. Diese vier Regelwerke sind fachlich zentral und derzeit nur strukturell erfasst.
4. **Datenbankschema rekonstruieren.** Da keine DDL vorliegt, sollte aus den 764 Skriptmethoden ein konsolidiertes Schema abgeleitet werden. Ohne dieses Schema bleiben Datenmigrationsanforderungen unvollständig.
**Nachrangig:**
5. **Startcode der Hosts und Buildpipelines lesen** — schließt die Lücken zu Transportsicherheit, Middleware und Prüfstrecke.
6. **`LicenseGuids` und `ApplicationKind` auszählen und den Lizenzkatalog vollständig erfassen** — Voraussetzung für ein Produktmodell im Zielsystem.
7. **Commit-Historie über die jüngsten 30 Einträge hinaus auswerten** — liefert Ticketbezüge und Änderungsgründe als zusätzliche `KONTEXT`-Belege, insbesondere für die 31 als `Workaround` markierten Anforderungen.
**Beobachtungen, die über den Auftrag hinaus für die Neuimplementierung bedeutsam sind:**
- **26 Konsolidierungskandidaten** wurden identifiziert (`Traceability.md`, Abschnitt 4). Die größten Hebel sind: eine statt zwei Schnittstellengenerationen (2.618 gegenüber 160 Operationen), ein statt zwei Einstellungsregister (1.219 Werte), ein statt zwei Persistenzpfade je Beleg, Wegfall der doppelten Datenzugriffsimplementierung im Client, ein statt sieben Protokollmodelle.
- **31 Anforderungen tragen den Status `Workaround`.** Sie markieren historische Sonderwege, die in der Validierung vorrangig zu prüfen sind. Fachlich am kritischsten: die ungesalzene SHA-1-Kennwortablage (SwRS-044), die erneute Passwortabfrage im Speichervorgang bei Mindestpreisunterschreitung (StRS-011, laut Codekommentar mit moderner Authentifizierung unvereinbar), die Kennzeichnung von Belegvorlagen über eine negative Belegnummer (SwRS-001) und das Übergehen bekannter Sicherheitswarnungen im Bauvorgang (SyRS-073).
- **Die Codebasis ist überdurchschnittlich gut dokumentiert.** 44 Dokumente unter `docs/` beschreiben Architektur, Konventionen und mehrere Fachbereiche in einer Qualität, die die Analyse deutlich beschleunigt hat. Für eine Folgeiteration empfiehlt sich, diese Dokumente zuerst vollständig zu lesen und erst danach gezielt im Code zu verifizieren — in diesem Lauf wurde umgekehrt vorgegangen, was mehrfach zu redundanter Suche führte.
- **Eine als Hypothese formulierte Aussage konnte im Lauf selbst widerlegt werden** (Sitzungsgültigkeit, siehe `Hypothesen.md`, Nachtrag). Das ist ein Hinweis darauf, dass die verbleibenden Hypothesen mit begrenztem Aufwand klärbar sind und die Hypothesenquote von 3,8 % in einer Folgeiteration weiter sinken kann.
### 6.4 Einschätzung der Belastbarkeit
Die Spezifikation ist als Grundlage für eine Neuimplementierung **im abgedeckten Bereich belastbar**, insbesondere für Belegverarbeitung, Berechtigungen, Authentifizierung und Betrieb. Sie ist **nicht vollständig**: Rund 20 Fachbereiche fehlen, und in den Bereichen der Tiefe C sind Rechenregeln nicht abgesichert. Eine Neuimplementierung allein auf dieser Fassung würde die fehlenden Bereiche übersehen. Die Spezifikation eignet sich daher als **Kern und Gerüst**, das in mindestens einer weiteren Iteration um die in Abschnitt 6.3 genannten Punkte zu ergänzen ist.
Die analysierte Codebasis wurde ausschließlich gelesen; im Arbeitsverzeichnis wurde keine Datei verändert.
@@ -0,0 +1,87 @@
# Glossar
Domänen- und Systembegriffe, die in `StRS.md`, `SyRS.md` und `SwRS.md` verwendet werden.
Jeder Eintrag nennt den Artefaktbeleg, aus dem der Begriff abgeleitet ist.
---
## A — Fachbegriffe der Domäne
| Begriff | Bedeutung im System | Beleg |
|---|---|---|
| **Abholschein** (`PickupList`, `AbholKopf`/`AbholPos`) | Kundenbeleg über die Abholung bereits gelieferter Ware; Endpunkt der Belegkette (keine Weiterverarbeitung). | `CentronObjectKindNumeric.PickupListClass = 5`; `PickupListSpecificLogic.CanBeForwardedInto()` = leer |
| **Aktionspreis** (`ActionPrice`) | Zeitlich befristeter Sonderpreis eines Distributors oder Herstellers für einen Artikel, mit `GueltigAb`/`GueltigBis`. | Tabelle `HerstellerArtikAktionspreis`; `ActionPriceBL` |
| **Anlage / AnlageArt** | Historische Sammelbezeichnung für Belege; `AnlageI3D` + `AnlageArt` referenzieren einen Beleg beliebiger Art im gemeinsamen Protokoll `AnlageLog`. | `docs/reference/receipts/receipts-backend-architecture.md`, Abschnitt „AnlageLog Table“ |
| **Ausgleichsartikel** (Balance Article) | Technischer Artikel, über den Über- oder Unterdeckungen eines Vertragskontingents abgerechnet werden. | `ReceiptItemSpecialArticleHelperBL.GetBalanceArticleI3D()` |
| **Barrechnung** (`IsCashAsset`) | Sofort bezahlte Rechnung; nicht stornierbar und nicht in eine Gutschrift weiterverarbeitbar. | `ReceiptInvoiceBL.CancelInvoice`; `InvoiceSpecificLogic.CanBeForwardedIntoForUIOverwrite` |
| **Beleg** (`Receipt`) | Oberbegriff für Kunden- und Lieferantenbelege; besteht aus Kopf (`*Kopf`) und Positionen (`*Pos`). | `ReceiptBase`; `CentronObjectKindNumericExtensions.IsReceipt()` |
| **Belegkette / Weiterverarbeitung** (Forwarding) | Übergang von einem Beleg in einen Folgebeleg unter Übernahme von Positionen und Mengen. | `IReceiptSpecificLogic.CanBeForwardedInto()`; `ReceiptProgressionBL` |
| **Belegversion** (`Version`) | Nummerierter Änderungsstand eines Belegs; Vorstände werden in `*KopfVersions`/`*PosVersions` aufbewahrt. | `ReceiptBase.Version`; `ReceiptBL.SaveReceipt` (Versionsprüfung) |
| **Belegvorlage** (Template) | Beleg mit negativer Belegnummer und dem festen Datum 1970-01-01; dient als Muster für neue Belege. | `ReceiptBase.IsTemplate => Number < 0`; `ReceiptBL.SaveReceipt` |
| **Einschränkendes Recht** (restricting right) | Recht, dessen Besitz den Zugriff *verringert* (z. B. „nur eigene Tickets“, „nur eigene Filiale“), statt ihn zu erweitern. | `CentronRights.md` („This is a **restricting right**“); `UserRightsConst.…SHOW_HELPDESK_ONLY_OWN` |
| **Filiale** (`Branch`, `Filiale`) | Organisatorische Untereinheit eines Mandanten; bestimmt Nummernkreis und Zugriffsbeschränkung von Belegen. | `ReceiptBase.BranchI3D`; `ReceiptBL.CanUserCreateReceiptsInBranch` |
| **Gutschrift** (`CreditVoucher`, `GutKopf`/`GutPos`) | Kundenbeleg zur Korrektur einer Rechnung; nur aus einer Rechnung erzeugbar, Endpunkt der Kette. | `CreditVoucherSpecificLogic.CanBeForwardedFrom()` = {InvoiceClass} |
| **Helpdesk / Ticket** (`Helpdesk`) | Serviceanfrage mit konfigurierbarem Status, Typ, Priorität und Kategorien. | `HelpdeskBL`; `HelpdeskState`; `CentronObjectKindNumeric.HelpdeskClass = 10` |
| **Kontingent** (Contingent) | In einem Vertrag vereinbartes Leistungsvolumen in Stunden oder Betrag, dessen Verbrauch fortgeschrieben wird. | `IReceiptWithContingent`; `ReceiptBL.WriteReceiptLogs` |
| **Kontingentgrenze** (`ContingentLimitKinds`) | Schwelle für die Kontingentüberwachung, wahlweise prozentual oder absolut. | `ContingentLimitKinds { Percent = 0, Absolute = 1 }` |
| **Kreditlimit** (`CreditLimit`) | Höchstbetrag offener Forderungen je Kunde, netto oder brutto gerechnet. | `ReceiptBL.CheckIfCustomerLimitIsReached`; `CreditLimitCalculationKind` |
| **Lieferantenbeleg** (Supplier Receipt) | Einkaufsbeleg: Lieferantenangebot, Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift. | `CentronObjectKindNumericExtensions.IsSupplierReceipt()` |
| **Mandant** (`Mandant`) | Firmenkennung mit eigener Anschrift und eigenen Nummernkreisen; genau ein Mandant trägt `Standard = 1`. | `MandatoryBL.GetNumberGroup` (SQL über `Mandant`) |
| **Mahnstufe** (Dunning Level) | Eskalationsstufe im Mahnwesen; ab einer konfigurierbaren Stufe wird die Belegneuanlage gesperrt. | `IReceiptSpecificLogic.BlockNewReceiptsDunningLevel` |
| **Mindestpreis** (`MinPrice`) | Am Artikel hinterlegte Preisuntergrenze für Kundenbelege. | `ReceiptBL.CheckArticleMinPrices`; `Article.MinPrice` |
| **Nebenlager** (Secondary Stock) | Zusätzliches Lager neben dem Hauptlager; Positionen mit `WarehouseI3D != -1` unterliegen einer Sonderprüfung. | `ReceiptArticleBookingBL.ValidateArticleWarehouses`; `SecondStockArticleBL` |
| **Nummernkreis** (`NumberGroup`, `Nummernkreis`) | Zählerdefinition je Objektart, Mandant und optional Filiale, mit Bereich, Intervall und aktuellem Stand. | `NumberGroupBL`; Tabelle `Nummernkreis` |
| **Provisionsschema** (`ReceiptProvisionSchema`) | Regelwerk zur Ermittlung von Vertriebsprovisionen, Kunden und Mitarbeitern zuordenbar. | `ReceiptProvisionSchema*`-Entitäten; `ReceiptProvisionSchemaBL` |
| **RMA** (Return Merchandise Authorization) | Rücksende- und Reparaturvorgang mit eigenen Nummern für Annahme, Vorgang und Rücksendung. | `RmaBL`; `NumberGroupEnum.RepairEntrance` / `.RMANumber` / `.Reshipment` |
| **Sonderpreis** | Kunden- oder vertragsbezogener abweichender Verkaufspreis; Grundlage des Warenkorbsortiments im Portal. | `CustomerSpecialArticleBL`; `README.md`, Abschnitt „WebCart“ |
| **Stammblatt** (`MasterDataList`) | Belegartige Auflistung der beim Kunden befindlichen Geräte/Objekte, u. a. Grundlage von Wartungsverträgen. | `CentronObjectKindNumeric.MasterDataListClass = 25`; `ReceiptContractBL.AddMasteDateListsToContract` |
| **Vertrag** (`Contract`, `VertragKopf`/`VertragPos`) | Dauerbeleg für wiederkehrende Leistungen mit Abrechnungsintervall, Laufzeit und Kontingent. | `ReceiptContract`; `ContractSpecificLogic` |
| **Vertragsabrechnung, vor-/nachschüssig** (`BillingKinds`) | Abrechnung zu Beginn (`Billingadvance`) oder zum Ende (`Billingarrear`) der Leistungsperiode. | `BillingKinds` mit `[Description("vorschüssig")]` / `("nachschüssig")` |
| **Warenkorb** (`ReceiptCart`, WebCart) | Kundenseitig gefüllter Angebotsbeleg im Portal, der nach Freigabe in einen Auftrag überführt wird. | `ReceiptCartBL`; `ReceiptCartReleaseSystemBL`; `CentronObjectKindNumeric.ReceiptCart = 7600143` |
| **Web-Account** (`WebAccount`) | Externes Benutzerkonto eines Kunden für das Portal; eigenes Rechtemodell. | `WebAccountBL`; `WebAccountRightsConst` |
| **Web-Angebot / C-Sign** (`WebOffer`) | Online zur Kundenfreigabe bereitgestelltes Angebot mit eigenem Zustandsmodell und digitaler Unterschrift. | `WebReceiptState`; `PdfSigningBL`; Commit „C-Sign (WebOffer & Acceptance)“ |
| **Zeiteintrag** (`HelpdeskTimer`) | Erfasste Arbeitszeit an einem Ticket mit Start, Ende und Abrechenbarkeitskennzeichen. | `HelpdeskTimerBase` (`Start`, `Stop`, `Calculable`) |
| **ZUGFeRD / XRechnung** | Deutsche Standards für elektronische Rechnungen; ZUGFeRD als PDF mit eingebettetem XML, XRechnung als reines XML. | `InvoiceZugferdBL`; `ZugferdFileKind { Comfort, XInvoice }` |
---
## B — System- und Architekturbegriffe
| Begriff | Bedeutung im System | Beleg |
|---|---|---|
| **`I3D`** | Primärschlüsselspalte jeder Tabelle (`int IDENTITY(1,1)`); Fremdschlüssel tragen den Suffix `I3D`. | `docs/guides/database/database-conventions.md` |
| **Objektart** (`CentronObjectKindNumeric`) | Numerische Typkennung eines Objekts; zusammen mit der `I3D` bildet sie eine typübergreifende Referenz. | `CentronObjectKindNumeric` (über 250 Werte) |
| **Anwendungsart** (`ApplicationKind`) | Lizenzierte Anwendung, die sich am Web-Service anmelden darf; trägt erforderliche und ausschließende Rechte sowie eine Ablaufart. | `ApplicationKind.GetKindByLicenseGuid`; `ExpirationKind` |
| **Lizenz** (`LicenseGuids`) | GUID mit optionaler Anzahl, Ablaufdatum und Maximalversion; steuert die Verfügbarkeit von Modulen und Funktionen. | `docs/reference/security/licensing-system.md`; `LicenseManager` |
| **Recht** (`UserRightsConst`, Tabelle `Sichrech`) | Numerische Berechtigung im hierarchischen Rechteregister; `OwnerRecht` bildet die Hierarchie ab. | `UserRightsConst`; `docs/guides/development/add-a-new-right.md` |
| **Web-Recht** (`WebAccountRightsConst`) | Berechtigung für Web-Accounts im Kundenportal, disjunkt zum Mitarbeiter-Rechteregister. | `WebAccountRightsConst` |
| **Sitzungsticket** (`Ticket`) | Zeitlich begrenzter Sitzungsnachweis je Benutzer, Anwendungsart und Gerät. | `TicketBL` (`TicketExpireInMinutes = 30`) |
| **`AppUser`** | Interner Benutzerdatensatz (Tabelle `Sichbenu`), verknüpft mit einem `Personal`-Datensatz. | `Authenticator.ValidateAppUser` |
| **`LoggedInUser`** | Laufzeitobjekt der angemeldeten Identität; unterscheidet über `IsWebAccountLogin` Mitarbeiter und Web-Account. | `ReceiptBL.CanUserViewReceipt`; `ReceiptCartReleaseSystemBL` |
| **`ILogic` / `BL*Logic` / `WS*Logic`** | Vertragsschnittstelle des Clients mit zwei Implementierungen: Direktzugriff auf die Datenbank bzw. Aufruf des Web-Service. | `docs/getting-started/general-structure.md` |
| **`ClassContainer`** | Auflösungskomponente des WPF-Clients, die je Verbindungsart die passende `ILogic`-Implementierung bereitstellt. | `ClassContainer.Instance.WithInstance(...)` |
| **`Result` / `Result<T>`** | Einheitlicher Ergebnistyp mit `Status`, `Message`, `MessageCode` und `Data`. | `Centron.Interfaces.BL`; `docs/reference/architecture/results-and-responses.md` |
| **`SpecificLogics` / `IReceiptSpecificLogic`** | Strategiemuster für belegartabhängiges Verhalten (über 120 Vertragsmitglieder). | `IReceiptSpecificLogic.cs`; `SpecificLogics.cs` |
| **`*WebServiceBL`** | Schicht, die Entitäten in DTOs umwandelt und die Fachlogik für die Schnittstellen bereitstellt. | `ReceiptWebServiceBL`; AutoMapper-Profile unter `WebServices/ObjectMapperConfiguration/` |
| **Temporäre Legacy-Entität** | Schreibmodell auf die deutschsprachigen Alttabellen; wird von den `SaveReceipt*Repository`-Klassen befüllt. | `Centron.Entities/Entities/DbEntities/`; `Centron.DAO/Mappings/TemporaryEntities/` |
| **Skriptmethode** (`ScriptMethodNNNNN`) | Typisierte Datenbankmigration mit Skriptnummer und Mindest-Anwendungsversion; Ausführungsstand in `DBUpdate`. | `ScriptEngineBL`; 764 Klassen unter `ScriptMethods/Scripts/` |
| **Anwendungseinstellung** | Konfigurationswert in `ApplicationSettings` (aktuell) oder `Stammdat` (Altbestand), typisiert über Enum-Kennungen. | `ApplicationSettingID` (491 Werte); `AppSettingsConst` (728 Werte) |
| **Modulregistrierung** | Deklarative Liste, die je Anwendungsmodul Recht- und Lizenzbedingung führt. | `ModuleRegistration._modules`; `ModuleRegistrationItem.For<T>` |
| **Nexus / ServiceBoard** | Blazor-Server-Webportal für Mitarbeiter und Kunden; Produktname laut Branding „NEXOWARE ServiceBoard“. | `src/nexus/CentronNexus`; `appsettings.json` → `Branding.Title` |
| **EDI-Datentyp** (`EdiDataType`) | Kennung des eingelesenen Distributordokuments (Auftragsbestätigung, Lieferung, Rechnung). | `SupplierEdiBL.ApplyDistriToCentron` |
| **Belegprotokoll** (`ReceiptLog`, `AnlageLog`) | Feld- bzw. ereignisbezogene Änderungsaufzeichnung zu Belegen. | `ReceiptLogBL`; `ReceiptBL.WriteReceiptLogs` |
---
## C — Begriffe der Anforderungsdokumentation
| Begriff | Bedeutung in dieser Spezifikation |
|---|---|
| **`Fakt`** | Die im Artefakt unmittelbar beobachtbare technische Aussage (Prüfung, Constraint, Enum-Wert, Konfigurationseintrag), ohne Deutung. |
| **`Aussage`** | Die daraus abgeleitete fachliche Soll-Aussage. Trennt Beobachtung von Interpretation. |
| **`PRIMÄR`** | Beleg für eine im Code oder in der Datenbank durchgesetzte Regel. |
| **`SEKUNDÄR`** | Beleg aus UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter oder Enum-Beschreibung. |
| **`KONTEXT`** | Beleg aus Kommentar, Commit-Message, Ticketreferenz oder Entwicklerdokumentation. |
| **`[HYPOTHESE]`** | Kennzeichnung einer Aussage, die sich aus den lesbaren Artefakten nicht eindeutig ableiten lässt; die offene Frage steht in `Hypothesen.md`. |
| **`Status: belegt; Workaround`** | Die Anforderung ist belegt, die Implementierung ist jedoch erkennbar ein historischer Sonderweg oder Behelf und in der Validierung vorrangig zu prüfen. |
| **`Konsolidierung`** | Verweis auf Anforderungen, die dieselbe fachliche Funktion abbilden und im Zielsystem zusammenzuführen sind. |
@@ -0,0 +1,125 @@
# Hypothesen und offene Fragen
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48` (Branch `main`), 2026-08-25
Diese Datei sammelt alle Aussagen, die sich aus den lesbaren Artefakten **nicht eindeutig** ableiten ließen. Jede Hypothese nennt den belegten `Fakt`, die daraus gezogene, unsichere `Aussage`, die **fehlende Information** und einen konkreten **Klärungsweg**. Die Hypothesen sind zusätzlich als vollständige Anforderungsblöcke mit `Status: HYPOTHESE` in `SyRS.md` (Abschnitt 5) bzw. `SwRS.md` (Abschnitt 6) enthalten.
**Anzahl:** 7 (2 auf SyRS-Ebene, 5 auf SwRS-Ebene) von insgesamt 182 Anforderungen (3,8 %).
---
## H-01 — SwRS-070: Ablösung der ersten Barcodeimplementierung
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | Nebeneinander existieren `Warehousing/BarCode.cs`, `Warehousing/BarCodeCompact.cs`, `Warehousing/Barcode2/BarCode2.cs` sowie `Sales/CustomerAssets/BarcodeToPosition.cs` und `BarcodeToPosition2.cs`. Die aktuelle Belegverarbeitung verwendet ausschließlich `BarCode2` (`IReceiptSpecificLogic.GetBarcodePreviousReceipts(BarCode2 barcode)`). |
| **Unsichere Aussage** | `BarCode`/`BarcodeToPosition` sind ein abgelöster Vorgängerstand ohne aktive Schreibzugriffe und können bei der Migration entfallen. |
| **Fehlende Information** | Ob und von welchen Komponenten die alten Entitäten noch geschrieben werden, und ob produktive Datenbestände ausschließlich im alten Modell liegen. |
| **Klärungsweg** | (a) Alle Schreibzugriffe auf `BarCode` und `BarcodeToPosition` im gesamten Repository ermitteln. (b) In einer Produktivdatenbank die Datensatzzahlen und das Maximum von `ChangedDate` beider Tabellen vergleichen. |
| **Risiko bei falscher Annahme** | Verlust der Seriennummernhistorie bei der Datenmigration. |
| **Betrifft** | StRS-018, SyRS-033, SwRS-015 |
---
## H-02 — SwRS-071: Ablösung der ersten Inventurimplementierung
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | Unter `Warehousing/InventoryManagement/` bestehen `InventoryBL.cs` und `InventoryNewBL.cs`. `ReceiptArticleBookingBL.ValidateArticleWarehouses` ruft die **ältere** Klasse auf (`_inventoryBL.CheckArticleSecondaryStockSetting(...)`). |
| **Unsichere Aussage** | Inventuren laufen fachlich über `InventoryNewBL`; `InventoryBL` verbleibt nur für einzelne, nicht überführte Hilfsfunktionen. |
| **Fehlende Information** | Welche der beiden Klassen den produktiv genutzten Inventurablauf trägt und ob beide Abläufe parallel angeboten werden. |
| **Klärungsweg** | (a) Aufrufer beider Klassen erfassen und den Einstiegspunkt des Inventurmoduls (`InventoryAppModuleController`) verfolgen. (b) Fachexperte befragen, welcher Inventurablauf beim Kunden verwendet wird. |
| **Risiko bei falscher Annahme** | Migration des falschen Inventurablaufs; Verlust einer produktiv genutzten Funktion. |
| **Betrifft** | StRS-017, SyRS-032, SwRS-014 |
---
## H-03 — SwRS-072: Mandantenfähigkeit ohne Datentrennung
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | `ReceiptBase` trägt `BranchI3D`, aber keinen Mandantenschlüssel. `MandatorBL.GetDefaultMandator()` dient an mehreren Stellen als Rückfallwert. `NumberGroupBL.RefreshAllNumberGroups()` legt alle Filial-Nummernkreise am Standardmandanten an, mit dem Kommentar „The current number group system requires that all branch number groups are created on the default mandator“. |
| **Unsichere Aussage** | Mandanten sind lediglich eine Ausprägung von Firmendaten (Anschrift, Nummernkreise, Berichtskopf) und keine Datentrennungsgrenze; mehrere Endkunden auf einer Instanz sind nicht vorgesehen. |
| **Fehlende Information** | Ob es Tabellen mit `MandantI3D` gibt, deren Leseabfragen durchgängig danach filtern, und ob ein Betriebsmodell mit mehreren Endkunden je Datenbank existiert. |
| **Klärungsweg** | (a) Alle Tabellen mit einer Spalte `MandantI3D` auflisten und stichprobenartig prüfen, ob Abfragen darauf filtern. (b) Vertrieb/Produktverantwortung befragen, ob Mandanten je Kunde oder je Konzernstruktur eingesetzt werden. |
| **Risiko bei falscher Annahme** | Ein SaaS-Zielsystem würde auf einer nicht vorhandenen Trennungsschicht aufbauen; Datenvermischung zwischen Kunden. |
| **Betrifft** | StRS-004, SyRS-014 |
| **Migrationsrelevanz** | **Hoch** — die Mandantentrennung ist die zentrale Voraussetzung eines SaaS-Betriebs. |
---
## H-04 — SwRS-073: Wirksamkeit der Ticketsperre über mehrere Dienstinstanzen
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | `Authenticator` serialisiert Ticketprüfung und -erzeugung über ein statisches, prozesslokales Sperrobjekt (`private static readonly object _getExistingOrCreateTicketLock`). `WebServiceConfig` kennt `PublicWebServiceAddress` und `AdditionalServices`. |
| **Unsichere Aussage** | Die Lizenzobergrenze soll auch bei mehreren parallel betriebenen Dienstinstanzen eingehalten werden; die prozesslokale Sperre kann dies nicht leisten. |
| **Fehlende Information** | Ob ein Mehrinstanzbetrieb gegen dieselbe Datenbank überhaupt unterstützt wird und ob eine bislang nicht aufgefundene datenbankseitige Absicherung existiert (z. B. eindeutiger Index auf der Ticketkombination). |
| **Klärungsweg** | (a) Datenbankschema der Tickettabelle auf eindeutige Indizes prüfen. (b) Lasttest mit zwei Instanzen, Lizenzanzahl 1 und gleichzeitiger Anmeldung. (c) Betriebsdokumentation zum Lastausgleich einsehen. |
| **Risiko bei falscher Annahme** | Lizenzumgehung oder doppelte Ticketvergabe im horizontal skalierten Betrieb. |
| **Betrifft** | StRS-003, StRS-005, SyRS-004, SyRS-009, SwRS-046 |
---
## H-05 — SwRS-074: Verschlüsselung der Datenbankverbindungszeichenfolge
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | `WebServiceConfig` führt `DatabaseConnectionString` **und** `DatabaseConnectionStringPlain`. Zum Feld `SecretKey` vermerkt der Codekommentar ausdrücklich: „It is not used for encryption or decryption.“ |
| **Unsichere Aussage** | Die Verbindungszeichenfolge wird verschlüsselt abgelegt; das Klartextfeld deutet auf eine optionale oder nur teilweise wirksame Verschlüsselung hin. |
| **Fehlende Information** | Welches Verschlüsselungsverfahren verwendet wird, woher der Schlüssel stammt und welches der beiden Felder im Produktivbetrieb gefüllt ist. |
| **Klärungsweg** | (a) `WebServiceConfigSerializer` und die aufrufenden Stellen auf Ver-/Entschlüsselungslogik prüfen. (b) Konfigurationsdatei einer Testinstallation einsehen. (c) Betrieb befragen. |
| **Risiko bei falscher Annahme** | Fehlende Anforderung an einen Geheimnisspeicher im Zielsystem; Offenlegung von Datenbankzugangsdaten. |
| **Betrifft** | StRS-041, SyRS-066 |
---
## H-06 — SyRS-080: Aufbewahrungs- und Löschfristen für personenbezogene Daten
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | Es existieren ein DSGVO-Modul mit eigenem Recht und eigener Lizenz, `DsgvoBL`, Auftragsverarbeitungsverträge als eigene Objektart und ein stündlich laufender `DataQualityService`, dessen dokumentierte Aufgabe unter anderem „Clean up outdated data“ ist. Konkrete Fristen für personenbezogene Daten waren nicht auffindbar. |
| **Unsichere Aussage** | Das System löscht oder anonymisiert personenbezogene Daten nach definierten Fristen. |
| **Fehlende Information** | Die vollständige Aufgabenliste des `DataQualityService` und die je Aufgabe zugrunde liegende Frist; ferner, ob Löschregeln für Anrufprotokolle, Ticketverläufe, Anmeldeprotokolle und Web-Account-Daten bestehen. |
| **Klärungsweg** | (a) Klasse `DataQualityService` vollständig lesen und jede Aufgabe mit ihrer Frist dokumentieren. (b) Datenschutzbeauftragten zum Löschkonzept befragen. |
| **Risiko bei falscher Annahme** | Das Zielsystem übernimmt eine nicht vorhandene Löschsystematik oder verletzt Aufbewahrungspflichten. |
| **Betrifft** | StRS-036, SyRS-064 |
| **Anmerkung zur Analysetiefe** | Der `DataQualityService` konnte im Lauf nur über die Entwicklerdokumentation erfasst werden; die Implementierungsdatei wurde nicht gelesen (siehe `Analysebericht.md`, Abschnitt „Bekannte Lücken“). |
---
## H-07 — SyRS-081: Transportverschlüsselung als Pflichtvorgabe
| Feld | Inhalt |
|---|---|
| **Belegter Fakt** | `WebServiceConfig` sieht `WebServiceCertificateFilePath`/`WebServiceCertificatePassword` vor; das Portal kennt `Host.LinuxCertificatePath`/`LinuxCertificatePassword`, der voreingestellte Endpunkt lautet jedoch `http://localhost:8050/`. Eine Prüfung, die unverschlüsselte Verbindungen ablehnt, war nicht auffindbar. |
| **Unsichere Aussage** | Verbindungen werden ausschließlich verschlüsselt angenommen. |
| **Fehlende Information** | Ob die Hosts eine Umleitung auf HTTPS oder eine HSTS-Konfiguration erzwingen und ob der unverschlüsselte Endpunkt in Produktivinstallationen abgeschaltet wird. |
| **Klärungsweg** | (a) Startcode der Hosts (`Centron.Host`, `CentronNexus.Host`) auf Kestrel-/HTTPS-Konfiguration prüfen. (b) Betriebsanleitung `docs/guides/services/web-service-on-linux.md` sowie `docker/compose/compose.yaml` auswerten. (c) Testinstallation mit unverschlüsselter Verbindung ansprechen. |
| **Risiko bei falscher Annahme** | Zugangsdaten und Geschäftsdaten werden unverschlüsselt übertragen. |
| **Betrifft** | StRS-041, SyRS-066, SyRS-070 |
---
## Nachtrag: geprüfte und aufgelöste Hypothese
| Ursprüngliche Annahme | Ergebnis der Prüfung |
|---|---|
| „Sitzungstickets besitzen keine Gültigkeitsbegrenzung, da `GetExistingTicket` ein bestehendes Ticket unverändert zurückgibt.“ | **Widerlegt.** `TicketBL` implementiert Ablaufzeiten (30 Minuten Standard, 5 Minuten für den Monitoring-Connector, 1.440 Minuten für die Tagesvariante, konfigurierbar über `AppSettingsConst.TicketReleaseTime` mit Untergrenze 30 Minuten), eine gleitende Verlängerung (`RefreshTicketExpireDate`) und eine Bereinigung (`DeleteExpiredTickets`). Die Aussage wurde als belegte Anforderung **SyRS-011** aufgenommen. |
Dieser Nachtrag ist bewusst dokumentiert: Er zeigt, dass eine zunächst plausible Lücke durch gezieltes Nachlesen einer einzigen Datei aufgelöst werden konnte, und dient als Hinweis darauf, dass die verbleibenden Hypothesen ebenfalls mit begrenztem Aufwand klärbar sind.
---
## Priorisierung für die Validierung durch Fachexperten
| Rang | Hypothese | Begründung |
|---:|---|---|
| 1 | H-03 (Mandantentrennung) | Bestimmt die Grundarchitektur eines SaaS-Zielsystems. |
| 2 | H-07 (Transportverschlüsselung) | Sicherheitsrelevant, betrifft alle Kanäle und ist schnell prüfbar. |
| 3 | H-05 (Verbindungszeichenfolge) | Sicherheitsrelevant, bestimmt die Anforderung an einen Geheimnisspeicher. |
| 4 | H-06 (Löschfristen) | Rechtlich relevant (DSGVO), betrifft das Datenmodell des Zielsystems. |
| 5 | H-04 (Ticketsperre bei Skalierung) | Betrifft Lizenzkontrolle und horizontale Skalierbarkeit. |
| 6 | H-01 (Barcodemodelle) | Migrationsrelevant für die Seriennummernhistorie. |
| 7 | H-02 (Inventurmodelle) | Migrationsrelevant, aber auf ein Modul begrenzt. |
@@ -0,0 +1,918 @@
# StRS — Stakeholder Requirements Specification
**System:** c-entron ERP-Suite (NEXOWARE Systems GmbH)
**Normbezug:** ISO/IEC/IEEE 29148:2018, Abschnitt 9.3 (StRS)
**Erhebungsverfahren:** Reverse Requirements Engineering, statische Analyse der Codebasis
**Analysestand:** Commit `79c1142f48` (Branch `main`), Stand 2026-08-25
**Sprache:** Deutsch; technische Bezeichner in Originalsprache
---
## 1. Zweck und Geltungsbereich
Dieses Dokument beschreibt die fachliche Sicht auf das bestehende System: Wer nutzt es, mit welchen Geschäftszielen, und welche fachlichen Fähigkeiten muss ein Zielsystem (Web/SaaS-Neuimplementierung) mindestens abdecken.
Alle Aussagen sind aus Artefakten der Codebasis abgeleitet. Jede Anforderung führt mindestens einen Beleg. Aussagen ohne eindeutige Artefaktbasis sind als `[HYPOTHESE]` gekennzeichnet und zusätzlich in `Hypothesen.md` gesammelt.
**Belegklassifikation**
- `PRIMÄR` — im Code oder in der Datenbank durchgesetzte Regel (Prüfung, Constraint, Statuszuweisung, Autorisierungsfilter)
- `SEKUNDÄR` — UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter, Enum-`[Description]`
- `KONTEXT` — Kommentar, Commit-Message, Ticketreferenz, Entwicklerdokumentation unter `docs/`
---
## 2. Akteure und Systemkontext
| Akteur | Beschreibung | Nachweis |
|---|---|---|
| **Mitarbeiter-Benutzer (`AppUser`)** | Interner Benutzer mit Datensatz in `Sichbenu`, verknüpft mit einem `Personal`-Datensatz (Mitarbeiter) | `Centron.BL/Administration/Logins/Auth/Authenticator.cs` |
| **Web-Account (`WebAccount`)** | Externer Benutzer eines Kunden, Zugang zum Kundenportal, eigenes Rechtesystem | `Centron.BL/Administration/Logins/WebAccountBL.cs`, `WebAccountRightsConst.cs` |
| **Administrator** | Mitarbeiter-Benutzer mit Rechten aus `UserRightsConst.Administration.*` | `UserRightsConst.cs` |
| **Externe Systeme (Distributoren)** | ALSO, ALSO CH, Alltron, Herweck, Komsa, OpenTrans 2.1 — EDI-Belegaustausch | `Centron.BL/EDI/SupplierEDI/SupplierEdiBL.*.cs` |
| **Externe Systeme (Produktdaten)** | ITscope, Icecat | `src/apis/Centron.APIs.ITscopeDataAccess`, `.IcecatDataAccess` |
| **Externe Systeme (Logistik)** | GLS, Shipcloud | `src/apis/Centron.Api.Gls`, `.Shipcloud` |
| **Externe Systeme (Banking)** | FinAPI | `src/apis/Centron.APIs.FinAPI` |
| **Externe Systeme (Identität)** | Active Directory, OpenID Connect / Microsoft Entra ID, RADIUS-Server | `Centron.BL/Administration/Logins/Auth/*Authenticator.cs` |
| **Buchhaltung / Steuerberater** | Empfänger von Buchhaltungsexporten (u. a. DATEV) | `Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs` |
| **Lizenzserver** | Externe Instanz, verwaltet Lizenz-GUIDs, Anzahl, Gültigkeit | `docs/reference/security/licensing-system.md` |
**Auslieferungskanäle (Clients)**
- `c-entron.NET` — WPF-Desktop-Client (`src/centron/Centron.WPF.UI`)
- `c-entron Nexus` / `NEXOWARE ServiceBoard` — Blazor-Server-Webportal (`src/nexus/CentronNexus`)
- `Outlook Add-In` (`src/nexus/CentronNexus.OutlookAddIn`)
- `c-entron Web-Service` — REST-Dienst als Konsolen-/Windows-Dienst-/Container-Host (`src/webservice/Centron.Host*`)
---
## 3. Stakeholder-Anforderungen
### 3.1 Zugang, Identität und Berechtigung
```
ID: StRS-001
Titel: Zwei getrennte Benutzerarten (Mitarbeiter und Kunden-Web-Account)
Ebene: StRS
Typ: funktional
Akteur: Mitarbeiter-Benutzer, Web-Account
Vorbedingung: Ein Benutzerkonto existiert in der Datenbank.
Fakt: `LoggedInUser` unterscheidet über die Eigenschaft `IsWebAccountLogin` zwischen internem `AppUser` und externem `WebAccount`; für Web-Accounts existiert mit `WebAccountRightsConst` ein eigener, disjunkter Rechtesatz, und `CentronAuthorization` definiert die beiden Login-Typen "User" und "Webaccount" als getrennte Autorisierungs-Policies.
Aussage: Das System soll zwei fachlich getrennte Benutzerarten unterstützen: interne Mitarbeiter mit dem vollen ERP-Rechtemodell und externe Kunden-Web-Accounts mit einem eigenen, eingeschränkten Rechtemodell.
Ergebnis: Die Zugehörigkeit zu einer Benutzerart bestimmt, welche Rechteprüfung und welche Oberflächen anwendbar sind.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/CentronAuthorization.cs (`UserLoginType = "User"`, `WebAccountLoginType = "Webaccount"`, `LoginTypes`) - Begründung: Die beiden Login-Typen werden als eigenständige, durchgesetzte Autorisierungs-Policies registriert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Methode `CanUserViewReceipt` (Abweisung mit "Web-Benutzer haben keine Berechtigung Belege einzusehen.") - Begründung: Der Code verzweigt hart auf die Benutzerart und verweigert einen ganzen Funktionsbereich.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/WebAccountRightsConst.cs - Begründung: Eigener Rechte-Enum ausschließlich für Web-Accounts.
Prüfidee: Ein Web-Account-Login darf keinen Zugriff auf interne Mitarbeiterfunktionen erhalten; ein Mitarbeiter-Login darf nicht über Web-Account-Rechte autorisiert werden.
Tracelinks: SyRS-001, SyRS-002, SyRS-010, SwRS-020
Konsolidierung: Kandidat: StRS-018 (Kundenportal) — die Sichtbarkeit von Belegen für Web-Accounts ist an zwei Stellen unterschiedlich geregelt (`ReceiptBL.CanUserViewReceipt` vs. `WebAccountRightsConst.WEBRIGHT_SHOWALLINVOICES`).
Status: belegt
```
```
ID: StRS-002
Titel: Rechtebasierter Zugang zu Funktionsmodulen
Ebene: StRS
Typ: Sicherheit
Akteur: Mitarbeiter-Benutzer
Vorbedingung: Der Benutzer ist angemeldet; seine Rechte sind geladen.
Fakt: `ModuleRegistration` registriert jedes Anwendungsmodul nur, wenn `CheckRights(allRights)` erfüllt ist; die Rechte werden vor der Registrierung über `IAppRightsLogic.GetRightsFromCurrentUserAsync()` geladen. Serverseitig erzwingen `AuthorizeUserRightAttribute`, `AuthorizeAllUserRightsAttribute` und `AuthorizeAnyUserRightAttribute` dieselbe Rechteprüfung auf API-Ebene (403 bei fehlendem Recht).
Aussage: Das System soll den Zugang zu jedem Funktionsmodul über ein zentral gepflegtes, feingranulares Rechtesystem steuern und die Prüfung sowohl im Client als auch serverseitig durchsetzen.
Ergebnis: Ein Benutzer ohne das erforderliche Recht sieht das Modul nicht und erhält bei direktem API-Zugriff HTTP 403.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, `DoRegisterCentronModules()` (Filterung `.Where(f => f.CheckRights(allRights))`) - Begründung: Modulsichtbarkeit wird durch Rechteprüfung durchgesetzt.
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs, `UserRightAuthorizationFilter.OnAuthorization` (`new ForbidResult()` bei `!currentUser.HasUserRight(...)`) - Begründung: Serverseitige Durchsetzung derselben Regel.
- [SEKUNDÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (Kopfkommentar "NEW .NET MODULE RIGHTS START AT 20800000 / NEXT ID: 20800174") - Begründung: Zeigt das zentrale, fortgeschriebene Rechteregister.
- [KONTEXT] docs/guides/development/check-userrights.md - Begründung: Beschreibt die vorgesehene Prüfroutine in ViewModels, Modulen und BL.
Prüfidee: Für jedes Modul: Benutzer ohne das registrierte Recht anlegen → Modul darf nicht erscheinen und der zugehörige API-Aufruf muss 403 liefern.
Tracelinks: SyRS-005, SyRS-006, SwRS-021, SwRS-022
Konsolidierung: Kandidat: StRS-003 — Modulverfügbarkeit wird an derselben Stelle zusätzlich durch Lizenzen bestimmt; im Zielsystem sollten "Berechtigung" und "Produktumfang" als getrennte Konzepte modelliert werden.
Status: belegt
```
```
ID: StRS-003
Titel: Lizenzabhängiger Funktionsumfang
Ebene: StRS
Typ: funktional
Akteur: Betreiber (Lizenzgeber), Mitarbeiter-Benutzer
Vorbedingung: Der Kunde besitzt einen Lizenzsatz, der vom Lizenzserver bezogen wurde.
Fakt: Jede Registrierung in `ModuleRegistration` führt zusätzlich zur Rechteprüfung eine Lizenzprüfung der Form `LicenseManager.Instance.HasLicense(LicenseGuids.X) || LicenseManager.Instance.HasLicense(LicenseGuids.Centron)` aus. Auch Einstellungsseiten werden über `ICentronAppModuleSettingsControllerWithLicense` nachträglich entfernt, wenn die Lizenz fehlt. Lizenzen sind GUIDs mit optionaler Anzahl (`count`), Ablaufdatum und Maximalversion.
Aussage: Das System soll den verfügbaren Funktionsumfang pro Kunde über einen Satz von Einzellizenzen steuern, wobei eine Sammellizenz ("Centron") alle Einzelfunktionen freischaltet.
Ergebnis: Nicht lizenzierte Module und Einstellungsseiten werden nicht angeboten.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (z. B. `LicenseGuids.FlatRateBilling || LicenseGuids.Centron`; Entfernen von Settings über `settings.RemoveRange(settingsToRemove)`) - Begründung: Lizenzprüfung entscheidet durchgesetzt über Modulverfügbarkeit.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs, `AuthenticateUser` (`LicenseManager.CheckLicense(applicationKind, appVersion, userResult)` vor Ticketerstellung) - Begründung: Ohne gültige Lizenz kein Anmeldeticket.
- [KONTEXT] docs/reference/security/licensing-system.md - Begründung: Beschreibt Lizenzmodell (GUID, count, valid until date, valid until version) und die Unterscheidung `Applications` vs. `Only Licenses`.
Prüfidee: Lizenz X entziehen → das zugehörige Modul verschwindet; Anmeldung mit einer Anwendung ohne gültige `ApplicationKind`-Lizenz muss scheitern.
Tracelinks: SyRS-004, SwRS-023
Konsolidierung: Kandidat: StRS-002 — Lizenz- und Rechteprüfung sind im Bestand in einer Ausdrucksliste vermischt.
Status: belegt
```
```
ID: StRS-004
Titel: Mandanten- und Filialstruktur
Ebene: StRS
Typ: Daten
Akteur: Betreiber, Mitarbeiter-Benutzer
Vorbedingung: Mindestens ein Mandant (`Mandant`) mit Kennzeichen `Standard = 1` existiert.
Fakt: Nummernkreise werden je Mandant und optional je Filiale aufgelöst (`Nummernkreis.MandantI3D`, `Nummernkreis.FilialI3D`); jeder Beleg trägt `BranchI3D` und `BranchOrigin`; die Rechteprüfung kennt filialbeschränkende Rechte (z. B. `HasRightToCreateANewReceiptOnlyOwnBranch`).
Aussage: Das System soll Mandanten und Filialen als organisatorische Gliederung abbilden und Datenzugriff, Nummernvergabe sowie Auswertungen an dieser Gliederung ausrichten können.
Ergebnis: Belege, Nummernkreise und Sichtbarkeiten sind einer Filiale bzw. einem Mandanten zugeordnet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Mandatory/MandatoryBL.cs, `GetNumberGroup(...)` (SQL über `Nummernkreis`, `Filiale`, `Mandant` mit Priorisierung Filiale vor Standardmandant) - Begründung: Auflösungsreihenfolge Mandant/Filiale ist in SQL fest kodiert.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs (`BranchI3D`, `BranchOrigin`) - Begründung: Filialzugehörigkeit ist Bestandteil jedes Belegkopfes.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CanUserCreateReceiptsInBranch<TReceipt>` / `CanUserEditReceipt` - Begründung: Filialbezogene Zugriffseinschränkung ist durchgesetzt.
- [SEKUNDÄR] CentronRights.md, Abschnitt "Mitarbeiterauslastung — nur eigene Filiale" - Begründung: Fachliche Benennung des filialbeschränkenden Rechts.
Prüfidee: Benutzer mit Filiale A und dem Recht "nur eigene Filiale" darf keinen Beleg für Filiale B anlegen oder bearbeiten.
Tracelinks: SyRS-014, SyRS-015, SwRS-024
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-005
Titel: Mehrstufige Authentifizierung mit wählbarem Verfahren
Ebene: StRS
Typ: Sicherheit
Akteur: Mitarbeiter-Benutzer, Web-Account, Administrator
Vorbedingung: Der Web-Service ist konfiguriert (`WebServiceConfig`).
Fakt: Es existieren vier Authentifizierungsverfahren als eigene Klassen (`BasicAuthenticator`, `ActiveDirectoryAuthenticator`, `OpenIdConnectAuthenticator`, `WebAccountAuthenticator`) plus `FallbackAuthenticator`/`FailingAuthenticator`; eine optionale zweite Stufe wird über `TwoFactorAuthBL` mit den Validatoren `RadiusTwoFactorValidator` und `EmailTwoFactorValidator` erzwungen, gesteuert über `WebServiceConfig.TwoFactorAuthEnabled` und `TwoFactorAuthType`.
Aussage: Das System soll die Anmeldung wahlweise über Benutzername/Passwort, Active Directory oder OpenID Connect erlauben und optional eine zweite Faktorstufe (RADIUS oder E-Mail-Link) mit konfigurierbarer Gültigkeitsdauer erzwingen.
Ergebnis: Nur nach erfolgreicher Prüfung aller aktivierten Stufen erhält der Benutzer ein Sitzungsticket.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs, `AuthenticateInternal()` (Rückgabe `TwoFactorAuthFailed` bei fehlgeschlagener zweiter Stufe) - Begründung: Die zweite Stufe ist zwingender Bestandteil des Anmeldeergebnisses.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs, `ValidateTwoFactor` / `HasToValidateTwoFactor` - Begründung: Enthält die durchgesetzte Entscheidungslogik inkl. Gültigkeitsdauer in Tagen.
- [PRIMÄR] src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfig.cs (`TwoFactorAuthEnabled`, `TwoFactorAuthType`, `TwoFactorValidDurationInDays`, `RadiusServer*`, `MailTwoFactorAuth*`) - Begründung: Konfigurationsvertrag der Sicherheitsfunktion.
- [KONTEXT] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md - Begründung: Beschreibt das OpenID-Connect-Verfahren aus Betreibersicht.
Prüfidee: Bei aktivierter 2FA und `TwoFactorValidDurationInDays = 0` muss jede Anmeldung erneut eine zweite Faktorstufe verlangen.
Tracelinks: SyRS-001, SyRS-002, SyRS-003, SwRS-025, SwRS-026
Konsolidierung: nein
Status: belegt
```
### 3.2 Vertriebsbelege (Verkaufsprozess)
```
ID: StRS-006
Titel: Durchgängige Verkaufsbelegkette
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter
Vorbedingung: Ein Kunde (`Kunden`/`Account`) ist angelegt.
Fakt: Es existieren sieben Kundenbelegarten mit eigener Entität, Kopf-/Positionstabelle und Sicht: Angebot (`AngKopf`/`AngPos`), Auftrag (`AufKopf`/`AufPos`), Lieferschein (`LiefKopf`/`LiefPos`), Rechnung (`RechKopf`/`RechPos`), Abholschein (`AbholKopf`/`AbholPos`), Gutschrift (`GutKopf`/`GutPos`), Vertrag (`VertragKopf`/`VertragPos`). `CentronObjectKindNumericExtensions.IsCustomerReceipt` zählt genau diese sieben auf.
Aussage: Das System soll den Verkaufsprozess durchgängig über die Belegarten Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift und Vertrag abbilden.
Ergebnis: Jeder Geschäftsvorfall im Vertrieb ist einer dieser Belegarten zugeordnet und mit einer eindeutigen Belegnummer versehen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, `IsCustomerReceipt()` - Begründung: Abschließende Aufzählung der Kundenbelegarten im Code.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ (Unterverzeichnisse `Offers`, `Orders`, `DeliveryLists`, `Invoices`, `PickupLists`, `CreditVouchers`, `ContractLists`) - Begründung: Je Belegart eine eigene Entität, abgeleitet von `ReceiptBase`.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, `[Description]`-Attribute ("Angebot", "Auftrag", "Lieferschein", "Rechnung", "Abholschein", "Gutschrift", "Vertrag") - Begründung: Fachliche Benennung der Belegarten.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md, Tabelle "Receipt Types Hierarchy" - Begründung: Bestätigt Tabellen-/Sichtzuordnung.
Prüfidee: Für jede der sieben Belegarten lässt sich ein Beleg anlegen, speichern, erneut laden und mit einer Belegnummer ausgeben.
Tracelinks: SyRS-020, SyRS-021, SwRS-001, SwRS-002
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-007
Titel: Weiterverarbeitung von Belegen entlang definierter Übergänge
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter
Vorbedingung: Ein Quellbeleg existiert und enthält weiterverarbeitbare Positionen.
Fakt: Jede belegartspezifische Logik deklariert `CanBeForwardedFrom()` und `CanBeForwardedInto()`. Daraus ergibt sich die Matrix: Angebot → Auftrag/Lieferschein/Rechnung; Auftrag → Lieferschein/Rechnung/Vertrag; Lieferschein → Abholschein/Rechnung; Vertrag → Rechnung; Rechnung → Gutschrift; Abholschein und Gutschrift sind Endpunkte.
Aussage: Das System soll Belege ausschließlich entlang der definierten Übergänge weiterverarbeiten und dabei Positionen mit Mengenbezug in den Folgebeleg übernehmen.
Ergebnis: Der Folgebeleg referenziert den Quellbeleg; die weiterverarbeitete Menge wird im Quellbeleg als verarbeitet geführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Offers/OfferSpecificLogic.cs, `CanBeForwardedInto()` = {OrderClass, DeliveryListClass, InvoiceClass} - Begründung: Zulässige Zielbelegarten sind kodiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Orders/OrderSpecificLogic.cs, `CanBeForwardedInto()` = {DeliveryListClass, InvoiceClass, ContractClass} - Begründung: dito.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs, `CanBeForwardedInto()` = {CreditVoucherClass} und `CanBeForwardedIntoForUIOverwrite` (leeres Array bei `IsCashAsset`) - Begründung: Zusätzliche Einschränkung für Barrechnungen ist durchgesetzt.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/PickupLists/PickupListSpecificLogic.cs und `CreditVouchers/CreditVoucherSpecificLogic.cs`, jeweils `CanBeForwardedInto()` = leeres Array - Begründung: Belegt die Endpunkte der Kette.
Prüfidee: Versuch, einen Abholschein weiterzuverarbeiten, muss abgelehnt werden; Angebot → Gutschrift darf nicht angeboten werden.
Tracelinks: SyRS-022, SwRS-005
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-008
Titel: Belegversionierung als Änderungshistorie
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter, Revision
Vorbedingung: Ein gespeicherter Beleg existiert.
Fakt: `ReceiptBase.Version` ist Bestandteil jedes Belegkopfes. Zu jeder Kopf- und Positionstabelle existiert eine 1:1-Kopietabelle `*KopfVersions` / `*PosVersions` mit `OriginalI3D`. Beim Speichern prüft `ReceiptBL.SaveReceipt`, ob die Versionsnummer die erste, die aktuelle oder genau die nächste ist, und lehnt andernfalls mit "Der Beleg hat keine gültige Versionsnummer." ab.
Aussage: Das System soll jede fachlich relevante Änderung an einem Beleg als neue Belegversion speichern und alle Vorversionen unverändert aufbewahren.
Ergebnis: Zu jedem Beleg ist die vollständige Versionshistorie abrufbar; Versionssprünge sind ausgeschlossen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `SaveReceipt<T,TReceiptItem>` (Prüfung `isFirstVersion`/`isCurrentVersion`/`isNextVersion`, Fehlermeldung "Der Beleg hat keine gültige Versionsnummer.") - Begründung: Durchgesetzte Integritätsregel für die Versionsfolge.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs (`public virtual int Version`) - Begründung: Version ist persistiertes Kopfattribut.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md, Abschnitt "Version Tables: 1:1 Copies of Original Tables" - Begründung: Beschreibt Aufbau und Zweck der Versionstabellen.
Prüfidee: Beleg zweimal ändern → drei Versionen abrufbar, Version 1 und 2 inhaltlich unverändert.
Tracelinks: SyRS-023, SwRS-003, SwRS-004
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-009
Titel: Storno von Rechnungen unter fachlichen Sperrbedingungen
Ebene: StRS
Typ: funktional
Akteur: Vertriebs-/Buchhaltungsmitarbeiter mit Stornorecht
Vorbedingung: Eine Rechnung existiert und ist nicht bereits storniert.
Fakt: `ReceiptInvoiceBL.CancelInvoice` bricht mit einer jeweils eigenen Fehlermeldung ab, wenn (a) das Recht `RIGHT_RECHNUNGSTORNIEREN` fehlt, (b) die Rechnung bereits storniert ist, (c) es eine Barrechnung ist, (d) die Rechnung bereits weiterverarbeitet wurde, (e) die Rechnung bereits in die Buchhaltung exportiert wurde oder (f) es sich um eine Vertragsrechnung handelt, die nicht die zuletzt erzeugte Rechnung des Vertrags ist.
Aussage: Das System soll ein Rechnungsstorno nur zulassen, wenn der Benutzer berechtigt ist und die Rechnung weder weiterverarbeitet noch buchhalterisch exportiert wurde; bei Vertragsrechnungen darf nur die jeweils jüngste Rechnung storniert werden.
Ergebnis: Bei Erfolg entsteht eine neue Belegversion mit Status "storniert", zugehörige Zeiterfassungen werden gelöst und der Vertrag zurückgesetzt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/ReceiptInvoiceBL.cs, `CancelInvoice` (sechs Abbruchbedingungen, `newInvoiceVersion.State = ReceiptState.Canceled`) - Begründung: Vollständige, durchgesetzte Stornoregel inklusive Rechteprüfung.
- [SEKUNDÄR] Fehlermeldungen "Sie haben nicht das Recht um Rechnungen zu stornieren.", "…da Sie bereits exportiert wurde." - Begründung: Fachliche Formulierung der Sperrgründe.
Prüfidee: Rechnung exportieren → Storno muss mit der Exportmeldung abgelehnt werden. Zweitälteste Vertragsrechnung stornieren → Ablehnung.
Tracelinks: SyRS-024, SyRS-039, SwRS-006
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-010
Titel: Kreditlimitüberwachung je Kunde
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter, Debitorenbuchhaltung
Vorbedingung: Am Kunden ist ein Kreditlimit (> 0) mit einer Berechnungsart (netto/brutto) hinterlegt.
Fakt: `ReceiptBL.CheckIfCustomerLimitIsReached` summiert über alle limitrelevanten Belegarten den bereits genutzten Betrag, zieht die Vorversion des aktuellen Belegs ab und meldet eine Überschreitung inklusive Differenzbetrag und Aufschlüsselung je Belegart. Der Vorgang kann nur durch die explizite Freigabe `SaveAlthoughCustomerLimitExceeded` fortgesetzt werden.
Aussage: Das System soll beim Speichern eines Kundenbelegs das Kreditlimit des Kunden prüfen und bei Überschreitung eine ausdrückliche Freigabeentscheidung verlangen.
Ergebnis: Ohne Freigabe wird der Beleg nicht gespeichert; mit Freigabe wird gespeichert und die Überschreitung ist nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CheckIfCustomerLimitIsReached` (Berechnung `limitAvailable = customer.CreditLimit - limitUsed`, Abbruchbedingung `data.SaveAlthoughCustomerLimitExceeded == false`) - Begründung: Durchgesetzte finanzielle Kontrollregel.
- [SEKUNDÄR] Meldungstext "Das Limit von {…} wurde um {…} überschritten." - Begründung: Fachliche Formulierung.
Prüfidee: Kunde mit Limit 1.000 EUR, offener Auftrag über 900 EUR → neue Rechnung über 200 EUR muss die Limitmeldung auslösen.
Tracelinks: SyRS-025, SwRS-007
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-011
Titel: Mindestpreisschutz auf Artikelebene
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter, Vertriebsleitung
Vorbedingung: Am Artikel ist ein Mindestpreis (`MinPrice`) hinterlegt.
Fakt: `ReceiptBL.CheckArticleMinPrices` prüft für alle Artikelpositionen eines Kundenbelegs, ob der berechnete Nettopreis unter dem Artikelmindestpreis liegt. Benutzer mit dem Recht `Sales.Customer.CustomerCommon.Offer.ALLOW_IGNORE_MINIMUM_PRICE` sind ausgenommen. Andernfalls muss der Preis entweder auf den Mindestpreis angehoben werden oder eine erneute Authentifizierung mit Benutzername/Passwort erfolgen.
Aussage: Das System soll das Unterschreiten hinterlegter Artikelmindestpreise verhindern und eine Unterschreitung nur nach Sonderberechtigung oder erneuter Freigabeauthentifizierung zulassen.
Ergebnis: Preise unterhalb des Mindestpreises werden entweder korrigiert oder durch eine protokollierte Freigabe legitimiert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CheckArticleMinPrices` (Rechteprüfung, Vergleich `currentPrice.NetPrice >= minPrice`, `ChangeBasePrice(item, minPrice)`, erneute Authentifizierung über `AuthenticatorFactory`) - Begründung: Durchgesetzte Preisregel mit Freigabemechanismus.
- [KONTEXT] Codekommentar an derselben Stelle: "TODO Das funktioniert dann mit der Azure Authentifikation nicht mehr / Warum muss man sich hier überhaupt noch mal authentifizieren?" - Begründung: Weist die erneute Authentifizierung als historisch gewachsenen Sonderweg aus.
Prüfidee: Position unter Mindestpreis erfassen → Speichern muss ohne Sonderrecht abgewiesen oder mit Preiskorrektur beantwortet werden.
Tracelinks: SyRS-026, SwRS-008
Konsolidierung: nein
Status: belegt; Workaround (erneute Passwortabfrage im Speichervorgang, laut Codekommentar mit moderner Authentifizierung nicht kompatibel)
```
```
ID: StRS-012
Titel: Automatischer Belegabschluss bei vollständiger Verarbeitung
Ebene: StRS
Typ: funktional
Akteur: System (Belegverarbeitung)
Vorbedingung: Ein Beleg mit Positionen existiert.
Fakt: `AutomaticallyCloseReceiptHelperBL` setzt einen offenen Beleg auf "abgeschlossen", sobald alle Positionen als erledigt gelten (`QuantityComplete - QuantityProcessed <= 0` bzw. Sonderpositionsarten), und öffnet einen abgeschlossenen Beleg wieder, sobald eine Restmenge entsteht.
Aussage: Das System soll den Bearbeitungsstatus von Belegen automatisch aus dem Verarbeitungsgrad der Positionen ableiten und bei Rückabwicklung wieder öffnen.
Ergebnis: Der Belegstatus spiegelt jederzeit den tatsächlichen Verarbeitungsgrad wider, ohne manuelle Pflege.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/AutomaticallyCloseReceiptHelperBL.cs, `TryAutomaticallyCloseReceipt` / `TryAutomaticallyOpenReceipt` / `ItemIsFinished` - Begründung: Vollständig kodierte Zustandsregel.
- [KONTEXT] Codekommentar "SKA 2023-01-03 : Changed from IsZero to IsZeroOrNegative. Reason is a ticket where the customer booked the quantity too -1 …" - Begründung: Weist die Behandlung negativer Restmengen als nachträgliche Korrektur aus.
Prüfidee: Auftrag vollständig in Lieferschein überführen → Auftrag wechselt nach "abgeschlossen"; Lieferschein löschen/mindern → Auftrag wechselt zurück nach "offen".
Tracelinks: SyRS-021, SwRS-009
Konsolidierung: nein
Status: belegt; Workaround (Sonderbehandlung negativer Mengen)
```
### 3.3 Verträge und wiederkehrende Abrechnung
```
ID: StRS-013
Titel: Verträge mit periodischer Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Vertragsverwaltung, Abrechnung
Vorbedingung: Ein Kunde und abzurechnende Leistungen/Artikel sind vorhanden.
Fakt: Der Vertrag (`ReceiptContract`, Tabelle `VertragKopf`) trägt Abrechnungsintervallart (`BillingIntervalKinds`: Tag(e)=0, Monat(e)=1, Jahr(e)=2, Quartal(e)=3), Intervalldauer, Abrechnungsart (`BillingKinds`: vorschüssig=0, nachschüssig=1), Vertragsbeginn/-ende, Kündigungsdatum und ein Kennzeichen für automatische Abrechnung. Vertragsbelege lassen sich ausschließlich in Rechnungen weiterverarbeiten.
Aussage: Das System soll wiederkehrende Leistungen als Vertrag mit konfigurierbarem Abrechnungsintervall, vor- oder nachschüssiger Abrechnung und Laufzeit-/Kündigungsdaten führen und daraus Rechnungen erzeugen.
Ergebnis: Aus einem Vertrag entstehen periodisch Rechnungen; der Vertrag bleibt als Dauerbeleg bestehen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs und BillingKind.cs - Begründung: Abschließende Aufzählung der zulässigen Intervalle und Abrechnungsarten.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ContractLists/ContractSpecificLogic.cs, `CanBeForwardedInto()` = {InvoiceClass} - Begründung: Zulässiger Folgebeleg ist kodiert.
- [SEKUNDÄR] `[Description]`-Attribute "vorschüssig"/"nachschüssig", "Tag(e)"/"Monat(e)"/"Jahr(e)"/"Quartal(e)" - Begründung: Fachliche Benennung.
- [KONTEXT] docs/reference/receipts/contracts-backend.md - Begründung: Beschreibt Spalten und Vertragslebenszyklus.
Prüfidee: Vertrag mit Intervall "Monat(e)", Dauer 3, nachschüssig → Rechnungslauf erzeugt quartalsweise eine Rechnung mit Leistungszeitraum in der Vergangenheit.
Tracelinks: SyRS-027, SyRS-028, SwRS-010
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-014
Titel: Kontingentverwaltung innerhalb von Verträgen
Ebene: StRS
Typ: funktional
Akteur: Serviceleitung, Abrechnung
Vorbedingung: Ein Vertrag mit Kontingent (Stunden oder Betrag) existiert.
Fakt: Verträge führen verbrauchte Kontingente getrennt nach Stunden und Betrag (`ContingentUsedHours`, `ContingentUsedAmount`, `ContingentBalanceUsed*`), kennen Kontingentgrenzen mit den Arten `ContingentLimitKinds.Percent` und `.Absolute`, einen Ausgleichsartikel (`ContingentBalanceArticleI3D`) sowie Restwertführung. Jede Änderung dieser Werte wird über `ReceiptLogBL` protokolliert.
Aussage: Das System soll je Vertrag ein Leistungskontingent führen, dessen Verbrauch fortschreiben, Grenzwerte prozentual oder absolut überwachen und Über-/Unterdeckungen über einen Ausgleichsartikel abrechnen.
Ergebnis: Kontingentverbrauch und -restwert sind jederzeit auswertbar und jede Änderung ist protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `WriteReceiptLogs` (Protokolleinträge für `ContingentKind`, `ContingentValue`, `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentBalanceUsedHours`, …) - Begründung: Nachweis der geführten Kontingentgrößen und ihrer Protokollierung.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/ContingentLimitKinds.cs (`Percent = 0`, `Absolute = 1`) - Begründung: Abschließende Aufzählung der Grenzwertarten.
- [KONTEXT] docs/reference/receipts/contracts-backend.md, Abschnitt "Contingent Management" - Begründung: Fachliche Einordnung der Felder.
Prüfidee: Vertrag mit 10 h Kontingent, 12 h erfasste Zeit → 2 h müssen über den Ausgleichsartikel fakturiert werden.
Tracelinks: SyRS-029, SwRS-011
Konsolidierung: nein
Status: belegt
```
### 3.4 Einkauf, EDI und Lager
```
ID: StRS-015
Titel: Lieferantenbelegkette
Ebene: StRS
Typ: funktional
Akteur: Einkauf
Vorbedingung: Ein Lieferant (`Kreditor`) ist angelegt.
Fakt: `CentronObjectKindNumericExtensions.IsSupplierReceipt` zählt fünf Lieferantenbelegarten auf: Lieferantenangebot, Bestellung, Wareneingang, WE-Kalkulation (Lieferantenrechnung), Lieferantengutschrift. Zu allen existieren eigene BL-Verzeichnisse und `SaveReceipt*Repository`-Klassen.
Aussage: Das System soll den Einkaufsprozess über die Belegarten Lieferantenangebot, Bestellung, Wareneingang, Wareneingangskalkulation und Lieferantengutschrift abbilden.
Ergebnis: Beschaffungsvorgänge sind durchgängig belegt und mit Lagerbewegungen verknüpft.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs, `IsSupplierReceipt()` - Begründung: Abschließende Aufzählung im Code.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ (Verzeichnisse `SupplierOrders`, `SupplierDeliveryLists`, `SupplierInvoices`, `SupplierCreditVouchers`) - Begründung: Je Belegart eigene Geschäftslogik.
- [SEKUNDÄR] `[Description]`-Attribute "Bestellung", "Wareneingang", "WE-Kalkulation", "Li.-Gutschrift" - Begründung: Fachliche Benennung.
Prüfidee: Bestellung anlegen → Wareneingang buchen → WE-Kalkulation erzeugen; Lagerbestand und Einstandspreis müssen sich entsprechend ändern.
Tracelinks: SyRS-030, SwRS-012
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-016
Titel: Automatisierter Belegaustausch mit Distributoren (EDI)
Ebene: StRS
Typ: Schnittstelle
Akteur: Einkauf, externe Distributoren
Vorbedingung: Für den Lieferanten ist eine EDI-Konfiguration (`SupplierEdiConfigurations`) hinterlegt.
Fakt: `SupplierEdiBL` ist als partielle Klasse je Distributor implementiert (`.Also`, `.AlsoCH`, `.Alltron`, `.Herweck`, `.Komsa`, `.Opentrans`) und verarbeitet über `ApplyDistriToCentron` heruntergeladene Dateien abhängig von `EdiDataType` und `ObjectKind`. Für die Formatverarbeitung existieren eigene Gateway-Assemblies (`Centron.Gateway.EDI_*`, `Centron.Gateway.OpenTrans`).
Aussage: Das System soll Auftragsbestätigungen, Liefer- und Rechnungsdaten von Distributoren automatisiert einlesen und den zugehörigen Einkaufsbelegen zuordnen.
Ergebnis: Eingehende EDI-Dokumente aktualisieren Bestellungen und erzeugen Folgebelege ohne manuelle Erfassung; der Vorgang wird protokolliert.
Belege:
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs und die partiellen Klassen je Distributor - Begründung: Implementierte, distributor­spezifische Verarbeitungswege.
- [PRIMÄR] src/backend/Centron.Gateway/ (Assemblies `EDI_Also`, `EDI_AlsoCH`, `EDI_Alltron`, `EDI_Herweck`, `OpenTrans`) - Begründung: Formatparser als eigenständige Komponenten.
- [KONTEXT] docs/reference/edi/edi-architecture.md, Tabelle "Document Types Supported" - Begründung: Nennt je Distributor die unterstützten Dokumentarten (Komsa ohne Rechnung).
- [KONTEXT] docs/reference/edi/edi-import-rules.md - Begründung: Fachliche Importregeln.
Prüfidee: EDI-Testdatei je Distributor einspielen → zugehörige Bestellung erhält Auftragsbestätigungsdaten; Verarbeitungsprotokoll enthält einen Eintrag.
Tracelinks: SyRS-031, SwRS-013
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-017
Titel: Bestandsführung mit Haupt- und Nebenlägern
Ebene: StRS
Typ: funktional
Akteur: Lager, Vertrieb, Einkauf
Vorbedingung: Artikel mit Bestandsführung und mindestens ein Lager sind angelegt.
Fakt: `ReceiptArticleBookingBL` bucht Positionen abhängig von den belegartspezifischen Eigenschaften `UpdatesStock()`, `IncrementsStock()` und `ReceiptWithDelayedUpdateStock()` sowie vom Positionskennzeichen `ChangeStock`; Nebenlagerpositionen (`WarehouseI3D != -1`) werden zusätzlich über `CheckArticleSecondaryStockSetting` validiert. Beim Speichern einer neuen Belegversion wird zunächst rückgebucht (`UnBookArticles`) und anschließend neu gebucht (`BookArticles`).
Aussage: Das System soll Lagerbestände belegabhängig fortschreiben, Nebenläger unterstützen und bei Belegänderungen eine konsistente Rück- und Neubuchung durchführen.
Ergebnis: Der Lagerbestand entspricht jederzeit der Summe der gebuchten Belegpositionen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs, `BookArticles` / `UnBookArticles` / `UpdateStock` / `ValidateArticleWarehouses` - Begründung: Durchgesetzte Bestandslogik inklusive Nebenlagerprüfung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs (`UpdatesStock`, `IncrementsStock`, `ReceiptWithDelayedUpdateStock`) - Begründung: Vertrag, der die Bestandswirkung je Belegart festlegt.
Prüfidee: Lieferschein über 5 Stück speichern → Bestand −5; Menge auf 3 reduzieren → Bestand −3 (Nettoeffekt +2).
Tracelinks: SyRS-032, SwRS-014
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-018
Titel: Seriennummern- und Barcodeverfolgung
Ebene: StRS
Typ: funktional
Akteur: Lager, Service
Vorbedingung: Ein Artikel ist als seriennummernpflichtig gekennzeichnet.
Fakt: `ReceiptBL.SaveReceipt` ruft `CheckBarcodeCountsInTheReceipt` (ausreichende Anzahl Barcodes je Menge), `CheckIfAllNonActiveBarcodesAreStillInTheReceipt` (keine stillen Entfernungen) und `CheckForDuplicateBarcodes` auf; `NeedsAllBarcodesForQuantity` steuert die Pflicht je Belegart. Beim Anlegen einer neuen Version wird abgebrochen, wenn in der aktuellen Version noch aktive Seriennummern vorhanden sind.
Aussage: Das System soll Seriennummern (Barcodes) je Belegposition erfassen, deren Anzahl gegen die Positionsmenge prüfen, Doppelvergaben verhindern und den Verbleib über Belege hinweg nachvollziehbar halten.
Ergebnis: Zu jedem seriennummernpflichtigen Artikel ist der aktuelle und historische Belegbezug der Seriennummer bekannt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Aufrufe `CheckBarcodeCountsInTheReceipt`, `CheckForDuplicateBarcodes`, Abbruchmeldung "In der aktuellen Version dieses Belegs sind noch einige Seriennummern aktiv.") - Begründung: Durchgesetzte Prüfungen mit Abbruch.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptBarcodeBL.cs - Begründung: Zentrale Barcodelogik inkl. Buchungsentscheidung.
Prüfidee: Position mit Menge 3 und nur 2 erfassten Seriennummern speichern → Ablehnung mit Hinweis auf fehlende Barcodes.
Tracelinks: SyRS-033, SwRS-015
Konsolidierung: nein
Status: belegt
```
### 3.5 Service, Helpdesk und Zeiterfassung
```
ID: StRS-019
Titel: Ticketsystem (Helpdesk) als zentrales Servicewerkzeug
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Kunde (über Portal)
Vorbedingung: Ein Kunde ist angelegt.
Fakt: Der Helpdesk verfügt über einen eigenen, umfangreichen Rechtesatz (`UserRightsConst.Sales.Customer.Helpdesk.*` mit mindestens 24 dokumentierten Einzelrechten), über konfigurierbare Status (`HelpdeskState`), Typen, Prioritäten und Kategorien sowie über eine Historie (`HelpdeskHistoryBL`). Beim Speichern werden Pflichtfelder geprüft: Kunde immer, Priorität/Typ/Hauptkategorie abhängig von den Einstellungen `HelpdeskPriorityFieldIsRequired`, `HelpdeskTypeFieldIsRequired`, `HelpdeskMaincategoryFieldIsRequired`.
Aussage: Das System soll Serviceanfragen als Tickets mit konfigurierbaren Status, Typen, Prioritäten und Kategorien führen, Pflichtfelder konfigurierbar erzwingen und alle Statusänderungen historisieren.
Ergebnis: Jede Serviceanfrage ist eindeutig zugeordnet, nachverfolgbar und auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs, `DoValidateMandatoryFields` (Prüfung Kunde, Priorität, Typ, Hauptkategorie gegen `AppSettingsConst`) - Begründung: Durchgesetzte, konfigurierbare Pflichtfeldregel.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs, `CloseHelpdesk` (Setzen des konfigurierten Abschlussstatus, `ClosedAt`, Historieneintrag `HelpdeskHistoryType.Close`) - Begründung: Kodierter Abschlussvorgang.
- [SEKUNDÄR] CentronRights.md, Abschnitt "Helpdesk" (Rechte 1 bis 18 inkl. einschränkender Rechte) - Begründung: Fachliche Beschreibung des Helpdesk-Rechtemodells.
Prüfidee: Einstellung "Priorität ist Pflichtfeld" aktivieren → Ticket ohne Priorität muss mit "Keine Priorität ausgewählt." abgewiesen werden.
Tracelinks: SyRS-034, SyRS-035, SwRS-016
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-020
Titel: Einschränkende Rechte zur Sichtbarkeit von Tickets
Ebene: StRS
Typ: Sicherheit
Akteur: Servicemitarbeiter
Vorbedingung: Der Benutzer besitzt das Grundrecht "Helpdesk anzeigen".
Fakt: Neben dem Grundrecht `SHOW_HELPDESK` existieren die einschränkenden Rechte `SHOW_HELPDESK_ONLY_OWN` (nur Tickets, in denen der Benutzer Bearbeiter oder Verantwortlicher ist) und `SHOW_HELPDESK_ONLY_OWN_BRANCH` (nur Tickets der eigenen Filiale); analog für Anlage (`CREATE_HELPDESK_ONLY_OWN_BRANCH`), Zuweisung (`ASSIGN_HELPDESK_ONLY_TO_OWN_DEPARTMENTS`) und Zeitbearbeitung (`OWN_TIME_EDIT`).
Aussage: Das System soll Ticketsichtbarkeit und -bearbeitung über einschränkende Rechte auf eigene Vorgänge, die eigene Filiale bzw. die eigene Abteilung begrenzen können.
Ergebnis: Ein eingeschränkter Benutzer sieht ausschließlich die für ihn freigegebene Teilmenge der Tickets.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs (Konstanten `SHOW_HELPDESK`, `SHOW_HELPDESK_ONLY_OWN`, `SHOW_HELPDESK_ONLY_OWN_BRANCH`, `OWN_TIME_EDIT`) - Begründung: Die Rechte sind als auswertbare Konstanten im System verankert.
- [SEKUNDÄR] CentronRights.md, Abschnitte 1.1, 1.2, 2.1, 4, 7.1 (jeweils "This is a **restricting right**") - Begründung: Definiert die Semantik "einschränkendes Recht" fachlich.
Prüfidee: Benutzer mit `SHOW_HELPDESK_ONLY_OWN` darf ein Ticket eines Kollegen weder in Listen sehen noch direkt öffnen.
Tracelinks: SyRS-036, SwRS-017
Konsolidierung: Kandidat: StRS-002 — das Konzept "einschränkendes Recht" existiert nur implizit; im Zielsystem als eigener Rechtetyp modellieren.
Status: belegt
```
```
ID: StRS-021
Titel: Zeiterfassung auf Tickets mit Abrechenbarkeitskennzeichen
Ebene: StRS
Typ: funktional
Akteur: Servicemitarbeiter, Abrechnung
Vorbedingung: Ein Ticket existiert.
Fakt: `HelpdeskTimerBase` führt je Zeiteintrag Start, Stop, das Kennzeichen `Calculable` (abrechenbar), `IsPlanned` und `IsPrinted`. Zeiteinträge können in Belegpositionen überführt werden (`ReceiptItemTimerBL`), und beim Storno einer Rechnung werden die Timer-Referenzen wieder gelöst (`RemoveTimers`). Verschieben und Löschen von Zeiten sind nur zulässig, solange das Ticket nicht Bestandteil eines Belegs ist.
Aussage: Das System soll Arbeitszeiten je Ticket mit Start-/Endzeit und Abrechenbarkeitskennzeichen erfassen, sie in Rechnungspositionen überführen und nach Fakturierung gegen Änderung schützen.
Ergebnis: Erbrachte Leistungen sind lückenlos erfasst und eindeutig einem Abrechnungsbeleg zugeordnet oder als nicht abrechenbar markiert.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskTimerArea/HelpdeskTimerBase.cs (`Start`, `Stop`, `Calculable`, `IsPlanned`, `IsPrinted`) - Begründung: Datenmodell der Zeiterfassung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/ReceiptInvoiceBL.cs, `CancelInvoice` (`new ReceiptItemTimerBL(...).RemoveTimers(invoice, currentUser)`) - Begründung: Kopplung Zeiterfassung ↔ Faktura ist durchgesetzt.
- [SEKUNDÄR] CentronRights.md, Abschnitte 8 und 9 ("But only if the ticket is not part of a receipt.") - Begründung: Fachliche Sperrbedingung.
- [KONTEXT] Commit "Fix timer type (Calculable) (#98)" - Begründung: Belegt die fachliche Relevanz des Abrechenbarkeitskennzeichens.
Prüfidee: Zeit auf fakturiertem Ticket verschieben → Ablehnung; Rechnung stornieren → Zeit wieder abrechenbar.
Tracelinks: SyRS-037, SwRS-018
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-022
Titel: Vereinfachte Ticketabrechnung und Pauschalabrechnung
Ebene: StRS
Typ: funktional
Akteur: Abrechnung
Vorbedingung: Abrechenbare Ticketzeiten liegen vor.
Fakt: Es existieren getrennte, lizenz- und rechtegebundene Module: `TimerBillingAppModuleController` ("Vereinfachte Ticketabrechnung", Lizenz `SimplifiedTicketBilling`), `AutomatedBillingAppModuleController` ("Vertragsabrechnung", Lizenz `ContractBilling`) und `FlatRateProjectAppModuleController` ("Pauschalabrechnung", Lizenz `FlatRateBilling`).
Aussage: Das System soll unterschiedliche Abrechnungsmodelle für Serviceleistungen anbieten: Einzelabrechnung erfasster Zeiten, vertragsbasierte periodische Abrechnung und Pauschalabrechnung von Projekten.
Ergebnis: Erbrachte Leistungen können nach dem jeweils vereinbarten Modell in Rechnungen überführt werden.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "c-entron Module: Abrechnung" (drei Registrierungen mit Rechte- und Lizenzbedingung) - Begründung: Die drei Abrechnungsmodelle sind als eigenständige, unabhängig lizenzierbare Module realisiert.
- [KONTEXT] Commit "feat: added rights check for editing invoice or delivery list date in the settings of timer billing." - Begründung: Zeigt aktive Weiterentwicklung der vereinfachten Ticketabrechnung.
Prüfidee: Je Modell einen abrechenbaren Vorgang durchspielen und prüfen, dass genau eine Rechnung mit den erwarteten Positionen entsteht.
Tracelinks: SyRS-028, SyRS-038, SwRS-019
Konsolidierung: Kandidat: StRS-013 — drei getrennte Module erzeugen Rechnungen aus Leistungsdaten; im Zielsystem als ein Abrechnungsdienst mit Strategien zusammenführbar.
Status: belegt
```
### 3.6 Kundenportal und Selbstbedienung
```
ID: StRS-023
Titel: Kundenportal für Tickets, Belege und Dokumente
Ebene: StRS
Typ: funktional
Akteur: Web-Account (Kunde)
Vorbedingung: Für den Kunden ist ein Web-Account angelegt.
Fakt: `CentronNexus` ist eine eigenständige Blazor-Server-Anwendung mit den Bereichen `ServiceBoard` (Tickets, Kanban, MyDay, Terminplaner, Telefonate, Passwortmanager), `WebCart` (Shop), `WebOffer` (Angebotsfreigabe), `DocumentSigning` und `Management`. Der Zugang wird über Login-Typ-Policies, Employee-Rechte, Web-Account-Rechte, Lizenzen und Portnummern autorisiert (`CentronAuthorization`).
Aussage: Das System soll ein Webportal bereitstellen, über das Kunden Tickets erstellen und verfolgen, Belege einsehen, Angebote freigeben und Dokumente signieren können.
Ergebnis: Kunden bearbeiten ihre Vorgänge selbstständig; Mitarbeiter nutzen dasselbe Portal mit erweitertem Funktionsumfang.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/Shared/Authorization/CentronAuthorization.cs (Policies für `LoginType`, `EmployeeRights`, `WebAccountRights`, `License`, `Port`) - Begründung: Zugriffsmodell des Portals ist kodiert und durchgesetzt.
- [PRIMÄR] src/nexus/CentronNexus/ (Verzeichnisse `ServiceBoard`, `WebCart`, `WebOffer`, `DocumentSigning`, `Management`) - Begründung: Funktionsumfang als implementierte Bereiche.
- [SEKUNDÄR] src/nexus/CentronNexus.Host/appsettings.json, Abschnitt `Branding` (`"Title": "NEXOWARE ServiceBoard"`, `"LoginPageText": "Ihr cleveres Ticketsystem"`) - Begründung: Positionierung und Zielgruppe des Portals.
- [SEKUNDÄR] src/webservice/…/WebAccountRightsConst.cs (`WEBRIGHT_SHOWALLINVOICES`, `WEBRIGHT_SHOWCONTRACTS`, `WEBRIGHT_CREATEREQUEST`, …) - Begründung: Fachlicher Umfang der Kundenselbstbedienung.
Prüfidee: Web-Account ohne `WEBRIGHT_SHOWALLINVOICES` darf im Portal keine Rechnungen sehen.
Tracelinks: SyRS-010, SyRS-040, SyRS-041, SwRS-020
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-024
Titel: Webbasierter Warenkorb mit Freigabeprozess
Ebene: StRS
Typ: funktional
Akteur: Web-Account (Kunde), Vertrieb
Vorbedingung: Für den Kunden sind Sonderpreise gepflegt; der Web-Account besitzt Warenkorbrechte.
Fakt: `ReceiptCartBL` bildet den Warenkorb technisch als Angebot (`ReceiptOffer`) ab und stellt Suchen, Anlegen, Duplizieren, Positionsänderung, Import und PDF-Ausgabe bereit. `ReceiptCartReleaseSystemBL` überführt den freigegebenen Warenkorb per Belegweiterverarbeitung in einen Auftrag und schließt den Warenkorb (`EnsureCartIsClosed`). Anlegen und Speichern sind auf Web-Account-Logins beschränkt (`Guard.Not(currentUser.IsWebAccountLogin is false, "Only web-account logins can create carts.")`). Eigene Rechte steuern Prüfung und Bestellung (`WEBRIGHT_WEBCART2_CHECK_CART`, `WEBRIGHT_WEBCART2_ORDER_CART`).
Aussage: Das System soll Kunden einen Warenkorb auf Basis ihrer Sonderpreise anbieten, dessen Freigabe über einen mehrstufigen Prozess steuern und daraus einen Auftrag erzeugen.
Ergebnis: Aus einem freigegebenen Warenkorb entsteht genau ein Auftrag; der Warenkorb wird abgeschlossen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptCartReleaseSystemBL.cs, `SaveOrder` / `EnsureCartIsClosed` (Guard auf Web-Account-Login, Statuswechsel nach `ReceiptState.Completed`) - Begründung: Durchgesetzter Freigabe- und Abschlussvorgang.
- [PRIMÄR] src/webservice/…/WebAccountRightsConst.cs (`WEBRIGHT_WEBCART2_CATEGORY`, `WEBRIGHT_WEBCART2_CHECK_CART`, `WEBRIGHT_WEBCART2_ORDER_CART`) - Begründung: Eigenes Rechtemodell für den Freigabeprozess.
- [KONTEXT] README.md, Abschnitt "Contributing / 1. WebCart" ("The available articles come from the customers 'Sonderpreise'") - Begründung: Fachliche Herkunft des Sortiments.
Prüfidee: Warenkorb ohne `WEBRIGHT_WEBCART2_ORDER_CART` freigeben → Ablehnung; mit Recht → genau ein Auftrag entsteht, Warenkorb ist abgeschlossen.
Tracelinks: SyRS-041, SwRS-020
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-025
Titel: Online-Angebotsfreigabe und digitale Unterschrift
Ebene: StRS
Typ: funktional
Akteur: Web-Account (Kunde), Vertrieb
Vorbedingung: Ein Angebot wurde als Web-Angebot an den Kunden gesendet.
Fakt: `WebReceiptState` definiert die Zustände `SendToCustomer`, `FirstLoaded`, `InProcess`, `AcceptFullWebReceipt`, `AcceptWebReceiptWithChangeRequests`, `Rejected`, `WebOfferSign`, `WebOfferSignedWithoutSignature`, `WebReceiptShutDown`. Änderungswünsche werden als `WebReceiptItemChangeRequest` mit `ChangeRequestKind` erfasst. Für die Unterschrift existieren `PdfSigningBL`, die Einstellungsseite `PdfSigningSettingsAppModuleController` sowie die Portalseiten `SharedDocumentSignPage` / `IsolatedSignaturePad`.
Aussage: Das System soll Angebote online zur Kundenfreigabe bereitstellen, dabei vollständige Annahme, Annahme mit Änderungswünschen und Ablehnung unterscheiden und eine digitale Unterschrift auf dem PDF-Dokument erlauben.
Ergebnis: Der Freigabestatus des Angebots und die Änderungswünsche des Kunden sind im ERP nachvollziehbar; das unterschriebene Dokument liegt signiert vor.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs - Begründung: Abschließender Zustandsraum der Online-Angebotsfreigabe.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/WebReceipt/WebReceiptItemChangeRequest.cs und src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/ChangeRequestKind.cs - Begründung: Datenmodell für Änderungswünsche.
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs - Begründung: Implementierte Signaturfunktion.
- [KONTEXT] Commit "Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance) (#128)" - Begründung: Bestätigt Zweck und aktuelle Weiterentwicklung.
Prüfidee: Angebot versenden → Kunde nimmt mit Änderungswunsch an → Status `AcceptWebReceiptWithChangeRequests` und mindestens ein `WebReceiptItemChangeRequest` sind im ERP sichtbar.
Tracelinks: SyRS-042, SwRS-020
Konsolidierung: nein
Status: belegt
```
### 3.7 Finanzen und Buchhaltung
```
ID: StRS-026
Titel: Buchhaltungsexport an externe Finanzbuchhaltung
Ebene: StRS
Typ: Schnittstelle
Akteur: Buchhaltung, Steuerberater
Vorbedingung: Buchungsrelevante Belege liegen im gewählten Zeitraum vor.
Fakt: `BookKeepingExportBL` erzeugt getrennte Exportdateien für Kundenstammdaten, Lieferantenstammdaten, Kundenbuchungsdaten, Lieferantenbuchungsdaten und Kassenbuchdaten; Konfigurationen werden je Schnittstelle gespeichert (`BookKeepingExportConfiguration`), inklusive benutzerdefinierter Schnittstellen mit frei definierbaren Spalten (`BookKeepingExportCustomInterfaceColumn`). Der Exportzustand eines Belegs ist über `IsReceiptExported` abfragbar. Zusätzlich existiert das Modul "Datev Belegtransfer".
Aussage: Das System soll Stamm- und Buchungsdaten in konfigurierbaren Formaten an externe Finanzbuchhaltungen übergeben und exportierte Belege als übertragen kennzeichnen.
Ergebnis: Buchungsdaten sind je Zeitraum genau einmal exportiert; bereits exportierte Belege sind gegen Storno gesperrt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs (Methoden `GetCustomerBookingDataExportFile`, `ExportSupplierBookingDataFile`, `IsReceiptExported`, `GetCustomInterfaceColumns`) - Begründung: Implementierter Exportumfang und Zustandsführung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/ReceiptInvoiceBL.cs, `CancelInvoice` (`_bookKeepingExportBL.IsReceiptExported(invoice)` → Abbruch) - Begründung: Der Exportzustand ist eine durchgesetzte Sperre.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "Buchhaltung/Finanzen" (`DataExchangeAppModuleController`, `DatevOnlineAppModuleController`) - Begründung: Fachliche Benennung der Exportmodule.
Prüfidee: Rechnung exportieren → `IsReceiptExported` liefert `true` und der Storno wird abgelehnt.
Tracelinks: SyRS-039, SwRS-027
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-027
Titel: Elektronische Rechnungsstellung (ZUGFeRD / XRechnung)
Ebene: StRS
Typ: Schnittstelle
Akteur: Rechnungsstellung, Rechnungsempfänger, Gesetzgeber
Vorbedingung: Die elektronische Rechnungsstellung ist in den Einstellungen aktiviert.
Fakt: `InvoiceZugferdBL` erzeugt strukturierte Rechnungsdaten in zwei Ausprägungen (`ZugferdFileKind.Comfort`, `ZugferdFileKind.XInvoice`); `CustomZugferdPdfGenerator` bettet die XML-Daten in das PDF ein. Die Aktivierung erfolgt über die Einstellungen `IsZugferdInvoiceActive` (ID 10028) und `IsZugferdXRechnungActive` (ID 10144). `ZugferdParseBL` liest eingehende ZUGFeRD-Rechnungen; hierfür existiert ein eigener Controller `ZugferdImportController`.
Aussage: Das System soll Ausgangsrechnungen wahlweise als ZUGFeRD-Hybridrechnung oder als XRechnung erzeugen und eingehende ZUGFeRD-Rechnungen strukturiert einlesen.
Ergebnis: Ausgangsrechnungen erfüllen die gewählte E-Rechnungsspezifikation; Eingangsrechnungen können ohne manuelle Erfassung übernommen werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs und ZugferdFileKind.cs - Begründung: Implementierte Erzeugung beider Ausprägungen.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs (`IsZugferdInvoiceActive = 10028`, `IsZugferdXRechnungActive = 10144`) - Begründung: Schaltbare Aktivierung als Konfigurationseintrag.
- [PRIMÄR] src/webservice/Centron.Controllers/Controllers/v1/Receipts/ZugferdImportController.cs - Begründung: Eigener Endpunkt für den Rechnungsimport.
- [KONTEXT] docs/reference/zugferd-field-mapping.md und docs/reference/zugferd-feldzuordnung-anwender.md - Begründung: Vollständige Feldzuordnung als technische und Anwenderdokumentation.
- [KONTEXT] Commit "Fix: Correct discount calculation to retain sign for ZUGFeRD total check integrity (#112)" - Begründung: Belegt die Summenprüfung des Standards als aktives Thema.
Prüfidee: Rechnung mit aktivierter XRechnung erzeugen und mit dem KOSIT-Validator prüfen — die Prüfung muss fehlerfrei durchlaufen.
Tracelinks: SyRS-043, SwRS-028
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-028
Titel: Mahnwesen mit Mahnstufen und Belegsperre
Ebene: StRS
Typ: funktional
Akteur: Debitorenbuchhaltung
Vorbedingung: Überfällige Rechnungen liegen vor.
Fakt: Es existieren `DunningBL` und `DunningRunBL` sowie ein Modul "Mahnung" (`DunningOverviewAppModuleController`). Die belegartspezifische Logik stellt `BlockNewReceiptsDunningLevel(int customerOrSupplierI3D)` bereit, über die ab einer bestimmten Mahnstufe die Anlage neuer Belege blockiert werden kann. Ein eigener End-to-End-Testbereich `ReceiptDunningBlock` prüft dieses Verhalten.
Aussage: Das System soll überfällige Forderungen in Mahnläufen mit Mahnstufen verarbeiten und ab einer konfigurierbaren Mahnstufe die Anlage neuer Belege für den betroffenen Geschäftspartner sperren.
Ergebnis: Mahnungen werden erzeugt; Kunden in kritischer Mahnstufe erhalten keine neuen Belege.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs, `int? BlockNewReceiptsDunningLevel(int customerOrSupplierI3D)` - Begründung: Die Belegsperre je Mahnstufe ist Bestandteil des Belegverarbeitungsvertrags.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/DunningRunBL.cs - Begründung: Implementierter Mahnlauf.
- [SEKUNDÄR] tests/Centron.Tests.EndToEnd/Tests/ReceiptDunningBlock/ - Begründung: Eigener Testbereich für die Sperrlogik.
Prüfidee: Kunde auf Mahnstufe oberhalb der Schwelle setzen → Anlage eines neuen Auftrags muss abgelehnt werden.
Tracelinks: SyRS-044, SwRS-029
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-029
Titel: Zahlungsverkehr: SEPA, Zahlungseingang und Online-Banking
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung
Vorbedingung: Bankverbindungen und ggf. SEPA-Mandate sind hinterlegt.
Fakt: Es existieren die Module "SEPA" (`PaymentTransactionAppModuleController`), "Zahlungseingang" (`PaymentsAppModuleController`) und "OPOS" (`OposOverviewAppModuleController`). `PaymentTransactionBL` erzeugt Zahlungsverkehrsdateien; `OnlineBankingAccountTransactionsBL` gleicht Kontoumsätze gegen Belege ab und setzt dabei den Belegstatus (`ReceiptState.Completed` bei Bezahlung, Rücksetzung bei Stornobuchung). Die Anbindung erfolgt über FinAPI. SEPA-Mandate werden als eigene Objektart (`SepaContract`) geführt und beim Speichern eines Belegs geprüft (`CheckIfMandatIsNeeded`).
Aussage: Das System soll Lastschriften und Überweisungen im SEPA-Format erzeugen, Kontoumsätze über eine Bankschnittstelle einlesen und offene Posten automatisch ausgleichen.
Ergebnis: Bezahlte Rechnungen werden automatisch abgeschlossen; offene Posten sind auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Finances/OnlineBanking/OnlineBankingAccountTransactionsBL.cs (Statuswechsel abhängig von `undoBooking`, Zeilen um 928 und 1049) - Begründung: Durchgesetzte Kopplung Zahlung ↔ Belegstatus.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CheckIfMandatIsNeeded` (Kommentar "Abhängig: Zahlungskondition, Mandat") - Begründung: Mandatspflicht ist beim Speichern durchgesetzt.
- [PRIMÄR] src/apis/Centron.APIs.FinAPI/FinApiClient.cs - Begründung: Implementierte Bankschnittstelle.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "Buchhaltung/Finanzen" - Begründung: Fachliche Benennung der Module SEPA/Zahlungseingang/OPOS.
Prüfidee: Kontoumsatz zur offenen Rechnung einspielen → Rechnung wird als bezahlt abgeschlossen; Storno der Buchung setzt sie wieder auf offen.
Tracelinks: SyRS-045, SwRS-030
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-030
Titel: Provisionsermittlung für den Vertrieb
Ebene: StRS
Typ: funktional
Akteur: Vertriebsleitung, Personalabrechnung
Vorbedingung: Provisionsschemata sind definiert und Kunden zugeordnet.
Fakt: Es existieren die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`, `ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionEmployeeGoal`, `ReceiptProvisionEmployeeLevel` und `ReceiptProvisionItemEntity` sowie die Module "Provisionsauswertung", "Provisionsschemas verwalten" und "Provisionsschema Kundenzuordnung". `ReceiptBL.SaveReceipt` ruft `_receiptProvisionBL.SaveProvision(...)` als Bestandteil des Speichervorgangs auf; die belegartspezifische Logik liefert `IsProvisionRequired()`, `AutoProvisionForNewReceipts()` und `GetAutoProvisionShare()`.
Aussage: Das System soll Provisionen belegbezogen nach hinterlegten Schemata, Mitarbeiterzielen und Stufen ermitteln und beim Speichern des Belegs fortschreiben.
Ergebnis: Zu jedem provisionsrelevanten Beleg sind Provisionsanteile je Mitarbeiter gespeichert und auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (`this._receiptProvisionBL.SaveProvision(receipt, previousReceiptVersion, data, result);` im Speichervorgang) - Begründung: Provisionsfortschreibung ist fester Bestandteil der Belegspeicherung.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvisionSchema.cs u. a. - Begründung: Datenmodell der Provisionsermittlung.
- [SEKUNDÄR] tests/Centron.Tests.EndToEnd/Tests/ (Bereiche `ReceiptProvisions`, `ReceiptProvisionGoals`, `ReceiptProvisionLevels`, `ReceiptProvisionSchemaExpiration`) - Begründung: Umfang der abgesicherten Provisionsfälle.
Prüfidee: Beleg mit provisionsrelevanten Positionen speichern → Provisionsdatensätze entsprechen dem zugeordneten Schema.
Tracelinks: SyRS-046, SwRS-031
Konsolidierung: nein
Status: belegt
```
### 3.8 Weitere Fachdomänen
```
ID: StRS-031
Titel: Artikelstammdaten mit mehrstufiger Preisfindung
Ebene: StRS
Typ: funktional
Akteur: Einkauf, Vertrieb, Stammdatenpflege
Vorbedingung: Artikel sind angelegt.
Fakt: Neben dem Artikelstamm (`ArticleBL`) existieren Mengenstaffelpreise (`ArticleVolumePricesBL`), kunden- bzw. vertragsspezifische Sonderpreise (E2E-Bereiche `SpecialPrices`, `AccountArticleSpecialPrices`, `ContractSpecialPrices`), zeitlich befristete Aktionspreise (`ActionPriceBL`, Tabelle `HerstellerArtikAktionspreis` mit `GueltigAb`/`GueltigBis`), Projektpreisimport sowie ein Mindestpreis je Artikel.
Aussage: Das System soll den Verkaufspreis eines Artikels aus mehreren Preisquellen ermitteln — Grundpreis, Mengenstaffel, Kunden-/Vertragssonderpreis, zeitlich befristeter Aktionspreis — und dabei den Artikelmindestpreis als untere Schranke beachten.
Ergebnis: Die Preisfindung ist reproduzierbar und die verwendete Preisquelle nachvollziehbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ActionPriceBL.cs und ArticleVolumePricesBL.cs - Begründung: Implementierte Preisquellen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CheckArticleMinPrices` (`_articleBL.GetArticleByI3D(...).MinPrice`) - Begründung: Mindestpreis wird als Schranke ausgewertet.
- [KONTEXT] docs/reference/receipts/actionprice-system.md, Abschnitt "Data Flow / Filter by Date Range" - Begründung: Beschreibt die Gültigkeitsprüfung von Aktionspreisen.
Prüfidee: Artikel mit Grundpreis, Staffelpreis und aktivem Aktionspreis in einen Beleg einfügen → es gilt der fachlich vorgesehene Vorrang und der Mindestpreis wird nicht unterschritten.
Tracelinks: SyRS-026, SyRS-047, SwRS-032
Konsolidierung: Kandidat: StRS-011 — Preisfindung und Mindestpreisschutz sind auf mehrere BL-Klassen verteilt; im Zielsystem als ein Preisfindungsdienst zusammenführen.
Status: belegt
```
```
ID: StRS-032
Titel: Produktdatenbezug aus externen Katalogen
Ebene: StRS
Typ: Schnittstelle
Akteur: Stammdatenpflege
Vorbedingung: Zugangsdaten für den jeweiligen Katalogdienst sind konfiguriert.
Fakt: Es existieren eigenständige Zugriffsbibliotheken für ITscope (`ITscopeApi`) und Icecat (`IcecatApi`) mit jeweils eigenem Parser und Ausnahmetyp sowie eine Einstellungsseite `ICEcatSettingsController`. `ReceiptCartBL` lädt ITscope-Produktdaten für Warenkorbartikel (`LoadITscopeProducts`).
Aussage: Das System soll Produktstamm- und Verfügbarkeitsdaten aus externen Katalogdiensten beziehen und mit den eigenen Artikeln verknüpfen.
Ergebnis: Artikel sind mit Herstellerdaten, Beschreibungen und Verfügbarkeiten angereichert.
Belege:
- [PRIMÄR] src/apis/Centron.APIs.ITscopeDataAccess/ITscopeApi.cs, src/apis/Centron.APIs.IcecatDataAccess/IcecatApi.cs - Begründung: Implementierte Katalogschnittstellen.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptCartBL.cs, `LoadITscopeProducts(...)` - Begründung: Nutzung der Katalogdaten im Verkaufsprozess.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (`ICEcatSettingsController`) - Begründung: Konfigurierbarkeit als Einstellungsseite.
Prüfidee: Artikel mit Herstellernummer anlegen → Katalogabruf liefert Beschreibung und Bilder.
Tracelinks: SyRS-048, SwRS-033
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-033
Titel: Versandabwicklung über Logistikdienstleister
Ebene: StRS
Typ: Schnittstelle
Akteur: Versand
Vorbedingung: Ein Lieferschein ist erstellt; Versandeinstellungen sind gepflegt.
Fakt: Es existieren die Anbindungen `Centron.Api.Gls` und `Centron.Api.Shipcloud` mit eigenen Konstanten-, Fehler- und Logikklassen sowie die Einstellungsseiten `GlsSettingController`, `ShipcloudSettingController` und `ShippingMethodSettingsController`. Paketvorlagen werden als `ShipcloudPackageTemplate` gespeichert; Trackinglinks werden als eigene Objektart `DeliveryListTrackingLinks` geführt.
Aussage: Das System soll Versandaufträge an angebundene Logistikdienstleister übergeben, Versandetiketten erzeugen und Sendungsverfolgungslinks am Lieferschein bereitstellen.
Ergebnis: Zu einem Lieferschein liegen Versandlabel und Trackinginformation vor.
Belege:
- [PRIMÄR] src/apis/Centron.Api.Gls/CentronGlsLogic.cs und src/apis/Centron.Api.Shipcloud/CentronShipcloudLogic.cs - Begründung: Implementierte Versandschnittstellen.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (`DeliveryListTrackingLinks = 7600152`) - Begründung: Trackinglinks sind als eigene Objektart im Datenmodell verankert.
- [SEKUNDÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ShipcloudPackageTemplate.cs - Begründung: Paketvorlagen als Konfigurationsobjekt.
Prüfidee: Lieferschein an GLS übergeben → Label wird erzeugt und ein Trackinglink am Lieferschein gespeichert.
Tracelinks: SyRS-049, SwRS-034
Konsolidierung: Kandidat: StRS-033 selbst — GLS und Shipcloud sind getrennt implementiert; im Zielsystem über eine gemeinsame Versanddienst-Abstraktion zusammenführen.
Status: belegt
```
```
ID: StRS-034
Titel: RMA-/Werkstattabwicklung
Ebene: StRS
Typ: funktional
Akteur: Service, Werkstatt
Vorbedingung: Ein Rückläufer eines Kunden oder an einen Lieferanten liegt vor.
Fakt: `RmaBL` vergibt getrennte Nummernkreise für Reparaturannahme (`NumberGroupEnum.RepairEntrance`), RMA-Vorgang (`RMANumber`) und Rücksendung (`Reshipment`). Es existieren die Objektarten `RMA`, `RMACustomer`, `RMACreditor` und `RmaArticle` sowie das Modul "RMA/Werkstatt" und die Einstellungsseite `RmaSettingsController`. Belege können über das Kennzeichen `ClosedThroughRMA` bzw. `CheckCloseRMADeliverylistReceipt` von der automatischen Abschlusslogik ausgenommen werden.
Aussage: Das System soll Rücksendungen und Reparaturen als eigenständige Vorgänge mit eigener Nummernvergabe führen und ihre Wechselwirkung mit Liefer- und Rechnungsbelegen abbilden.
Ergebnis: Der Reparatur-/Rücksendevorgang ist vollständig belegt und beeinflusst den Status der zugehörigen Vertriebsbelege korrekt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/CustomerArea/RmaBL.cs (Nummernvergabe für `RepairEntrance`, `RMANumber`, `Reshipment`) - Begründung: Eigene, durchgesetzte Nummernkreise je Teilvorgang.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (`IReceiptClosedThroughRMA`, `CheckCloseRMADeliverylistReceipt`) - Begründung: Durchgesetzte Sonderbehandlung im Belegabschluss.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (`RMA = 7600127`, `RMACustomer = 7600144`, `RMACreditor = 7600145`) - Begründung: Eigenständige Objektarten.
Prüfidee: RMA-Vorgang anlegen → drei getrennte Nummern werden vergeben; der zugehörige Lieferschein wird nicht automatisch abgeschlossen.
Tracelinks: SyRS-050, SwRS-035
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-035
Titel: Projekt- und Aufgabenverwaltung
Ebene: StRS
Typ: funktional
Akteur: Projektleitung, Servicemitarbeiter
Vorbedingung: Ein Kunde bzw. ein Vorhaben ist erfasst.
Fakt: Es existieren getrennte Bereiche für CRM-Projekte (`CrmProjectBL`, eigener Nummernkreis `NumberGroupEnum.CRMProject`), Ticketprojekte (`TicketProject`, `TicketProjectTask`), Projektverwaltung (`ProjectManagementAppModuleController`) und Taskmanagement (`TaskManagmentAppModuleController`, Objektart `TaskManagementClass`) inklusive Wiederholungen (E2E-Bereich `TaskManagementRecurrence`). Belege können mit einem CRM-Projekt verknüpft werden (`ConnectWithCrmProject`, `CheckCrmProjectShouldBeSet`).
Aussage: Das System soll Vorhaben als Projekte mit zugeordneten Aufgaben und Tickets führen, wiederkehrende Aufgaben unterstützen und Belege einem Projekt zuordnen.
Ergebnis: Aufwände und Belege sind je Projekt auswertbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `ConnectWithCrmProject(receipt)` und `CheckCrmProjectShouldBeSet(...)` - Begründung: Projektzuordnung ist Bestandteil der Belegspeicherung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Customers/CrmProjects/CrmProjectBL.cs (eigener Nummernkreis) - Begründung: Projekte sind eigenständige nummerierte Objekte.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (`CrmProject = 5002760`, `TicketProject = 7600122`, `TicketProjectTask = 7600123`, `TaskManagementClass = 5101370`) - Begründung: Vier getrennte Projekt-/Aufgabenobjektarten.
Prüfidee: Beleg einem CRM-Projekt zuordnen → Projektauswertung weist Umsatz und Aufwand aus.
Tracelinks: SyRS-051, SwRS-036
Konsolidierung: Kandidat: StRS-035 selbst — CRM-Projekt, Ticketprojekt und Taskmanagement bilden überlappende Vorhaben-Konzepte ab; Vereinheitlichung im Zielsystem prüfen.
Status: belegt
```
```
ID: StRS-036
Titel: Datenschutzdokumentation (DSGVO) und Auftragsverarbeitung
Ebene: StRS
Typ: Sicherheit
Akteur: Datenschutzbeauftragter, Vertrieb
Vorbedingung: Ein Kunde ist angelegt.
Fakt: Es existieren `DsgvoBL`, das Modul "c-entron DSGVO" (`CentronDataSecurityAppModuleController`, Recht `DsgvoModule.ACCESS_DSGVO_MODULE`, Lizenz `CentronDSGVO`), die Objektart `OrderProcessingContract` (Auftragsverarbeitungsvertrag) mit eigener Einstellungsseite sowie Online-PDF-Dokumenthandler für Auftragsverarbeitungs- und SEPA-Verträge.
Aussage: Das System soll Auftragsverarbeitungsverträge je Kunde verwalten, als PDF bereitstellen und den Bearbeitungszugang über ein eigenes Recht schützen.
Ergebnis: Zu jedem Kunden ist der Status der Auftragsverarbeitungsvereinbarung dokumentiert und belegbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Documents/Dsgvo/DsgvoBL.cs und OrderProcessingContractOnlinePdfDocumentHandler.cs - Begründung: Implementierte Verwaltung und Dokumentbereitstellung.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (`Helper.HasRights(UserRightsConst.DsgvoModule.ACCESS_DSGVO_MODULE)`) - Begründung: Eigener Rechteschutz für den Datenschutzbereich.
- [SEKUNDÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (`OrderProcessingContract = 7600085`) - Begründung: Eigenständige Objektart.
Prüfidee: Benutzer ohne DSGVO-Recht darf das Modul nicht sehen; Auftragsverarbeitungsvertrag lässt sich als PDF erzeugen.
Tracelinks: SyRS-052, SwRS-037
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-037
Titel: Berichtswesen und Dokumentenerzeugung
Ebene: StRS
Typ: funktional
Akteur: alle Fachbereiche
Vorbedingung: Ein Berichtslayout ist im Reportmanagement hinterlegt.
Fakt: Es existieren eine eigene Reportengine (`Centron.BL/ReportEngine`) mit Vorlagenverwaltung, Reportobjekten und benutzerdefinierten PDF-Generatoren, das Modul "Reportverwaltung" (`ReportEngineAppModuleController`) sowie ein "Reportserver" für zeitgesteuerte Auswertungen. `IReceiptSpecificLogic.CanCreateReport(...)` entscheidet belegartabhängig, ob ein Bericht erzeugt werden darf; PDF-Exporteinstellungen (Schrifteinbettung, PDF-Konformitätsstufe) sind konfigurierbar.
Aussage: Das System soll aus Belegen und Auswertungsdaten druck- und versandfähige Dokumente erzeugen, deren Layouts verwaltbar sind, und die Erzeugung belegartabhängig freigeben.
Ergebnis: Jeder Beleg kann in der konfigurierten Form als PDF ausgegeben, gespeichert und versendet werden.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs, `Result CanCreateReport(...)` - Begründung: Freigabeentscheidung ist Teil des Belegvertrags.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs (`PdfExportStandardEmbeddingFonts = 10371` und die folgende PDF-Compliance-Einstellung) - Begründung: Konfigurierbare Ausgabeeigenschaften.
- [PRIMÄR] src/backend/Centron.BL/ReportEngine/CustomPdfGenerators/CustomZugferdPdfGenerator.cs - Begründung: Belegt die Kopplung von Berichtserzeugung und E-Rechnung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs (`ReportEngineAppModuleController`, `ReportServerAppModuleController`) - Begründung: Fachliche Benennung.
Prüfidee: Rechnung als PDF erzeugen → das Dokument entspricht dem hinterlegten Layout und der konfigurierten PDF-Konformitätsstufe.
Tracelinks: SyRS-053, SwRS-038
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-038
Titel: Telefonieanbindung (TAPI) und Anrufprotokollierung
Ebene: StRS
Typ: Schnittstelle
Akteur: Vertrieb, Service
Vorbedingung: Eine TAPI-Leitung ist eingerichtet.
Fakt: Es existieren `TapiBL`, `PhoneCallBL`, die Objektart `PhoneCall = 7600088`, das Modul "Telefonate" (`TelephonyCallLogAppModuleController`) sowie persönliche und globale Telefoneinstellungen (`PersonalPhoneSettingsController`, `PhoneSettingsController`).
Aussage: Das System soll ein- und ausgehende Telefonate erkennen, dem passenden Geschäftspartner zuordnen und als Anrufprotokoll speichern.
Ergebnis: Telefonate sind dem Kunden zugeordnet und im Kontaktverlauf sichtbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Accounts/TapiBL.cs und src/backend/Centron.BL/Tapi/PhoneCallBL.cs - Begründung: Implementierte Telefonielogik.
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (`PhoneCall = 7600088`) - Begründung: Anrufe sind eigenständige Objekte im Datenmodell.
- [KONTEXT] docs/reference/architecture/tapi.md - Begründung: Beschreibt die Anbindung.
Prüfidee: Eingehender Anruf einer erfassten Rufnummer → Anrufprotokolleintrag mit korrekter Kundenzuordnung.
Tracelinks: SyRS-054, SwRS-039
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-039
Titel: Deutschsprachige Benutzeroberfläche mit optionaler englischer Übersetzung
Ebene: StRS
Typ: nicht-funktional (Benutzbarkeit / ISO 25010: Usability)
Akteur: alle Benutzer
Vorbedingung: —
Fakt: Deutsche Texte liegen in den Basis-Ressourcendateien (`LocalizedStrings.resx`), englische Übersetzungen in `LocalizedStrings.en.resx`. Fehlermeldungen der Geschäftslogik sind durchgängig deutsch formuliert (z. B. "Der Beleg hat kein gültiges Datum.", "Aktuell werden leider noch keine Bar-Belege unterstützt."). `ResXManager.config.xml` verwaltet die Ressourcen.
Aussage: Das System soll seine Oberfläche und alle Benutzermeldungen primär in deutscher Sprache bereitstellen und eine englische Übersetzung als zweite Sprache unterstützen.
Ergebnis: Benutzer erhalten fachlich korrekte deutsche Begriffe; eine Sprachumschaltung auf Englisch ist möglich.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (deutschsprachige Fehlermeldungen im Speichervorgang) - Begründung: Meldungstexte sind unmittelbar im Verarbeitungspfad deutsch kodiert.
- [PRIMÄR] Ressourcendateien `LocalizedStrings.resx` / `LocalizedStrings.en.resx` (referenziert über `Centron.BusinessLogic.Resources.LocalizedStrings` in `BasicAuthenticator.cs`, `Authenticator.cs`) - Begründung: Zweisprachiges Ressourcensystem ist im Code genutzt.
- [KONTEXT] docs/getting-started/general-structure.md, Abschnitt "German-First Language Policy" - Begründung: Explizite Sprachvorgabe des Projekts.
- [KONTEXT] docs/guides/ui/localization.md - Begründung: Beschreibt das Lokalisierungsverfahren.
Prüfidee: Stichprobe von 20 Benutzermeldungen: alle liegen deutsch und mit englischer Entsprechung vor.
Tracelinks: SyRS-055, SwRS-040
Konsolidierung: Kandidat: SwRS-040 — ein Teil der Meldungen ist hart im Code kodiert statt über Ressourcen geführt.
Status: belegt
```
```
ID: StRS-040
Titel: Nachvollziehbarkeit aller geschäftsrelevanten Änderungen
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Sicherheit — Nachweisbarkeit)
Akteur: Revision, Geschäftsführung
Vorbedingung: —
Fakt: Jeder Beleg führt `CreatedByI3D`, `CreatedAt`, `CreatedThroughApplicationVersion`, `ChangedByI3D`, `ChangedAt`, `ChangedThroughApplicationVersion` und `ChangedThroughApplication`. Zusätzlich existieren die zentrale Protokolltabelle `AnlageLog` (Belegprotokoll je Belegart), `ReceiptLog`, `HelpdeskHistory`, `HelpdeskTimerLog`, `ArticleLog`, `AccessTokenLog` und ein Änderungsverfolgungsbereich `ChangeTracking`.
Aussage: Das System soll für Belege, Tickets, Artikel und sicherheitsrelevante Objekte festhalten, wer wann über welche Anwendung und Version welche Änderung vorgenommen hat.
Ergebnis: Änderungen sind nachträglich einem Benutzer, Zeitpunkt und Anwendungskanal zuzuordnen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs (sieben Audit-Felder) - Begründung: Auditinformationen sind Bestandteil jedes Belegkopfes.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (`receipt.ChangedAt = DateTime.Now; receipt.ChangedByI3D = currentUser.Employee.I3D; receipt.ChangedThroughApplication = application;`) - Begründung: Die Felder werden bei jedem Speichern zwingend gesetzt.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptLogBL.cs, `WriteReceiptLogs` in ReceiptBL.cs - Begründung: Feldbezogene Änderungsprotokolle.
- [KONTEXT] docs/reference/receipts/receipts-backend-architecture.md, Abschnitt "Shared Logging Infrastructure / AnlageLog" - Begründung: Beschreibt das zentrale Protokollmodell.
Prüfidee: Beleg über den Web-Service ändern → `ChangedThroughApplication` weist den Web-Service als Kanal aus, `ChangedByI3D` den handelnden Mitarbeiter.
Tracelinks: SyRS-056, SwRS-041
Konsolidierung: Kandidat: SwRS-041 — Protokollierung ist über `AnlageLog`, `ReceiptLog`, `*History`- und `*Log`-Tabellen verteilt; im Zielsystem als ein Auditmodell zusammenführen.
Status: belegt
```
```
ID: StRS-041
Titel: Betrieb wahlweise als Windows-Installation oder Container
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Übertragbarkeit)
Akteur: Betreiber / IT-Betrieb
Vorbedingung: Ein Microsoft SQL Server ist verfügbar.
Fakt: Der Web-Service liegt als Konsolenanwendung (`Centron.Host.Console`), als Windows-Dienst (`Centron.Host.WindowsService`) und als Containerabbild vor; `docker/Dockerfile` baut das Nexus-Portal auf `dotnet/runtime:10.0-alpine` mit `TZ=Europe/Berlin`. Für die Windows-Installation existieren WiX-Installer unter `deployment/WixSharpInstaller`. Eine Anleitung für den Linux-Betrieb des Web-Service ist vorhanden.
Aussage: Das System soll sowohl als klassische Windows-Installation beim Kunden als auch containerbasiert betrieben werden können.
Ergebnis: Dieselbe Anwendungsversion ist in beiden Betriebsarten lauffähig.
Belege:
- [PRIMÄR] docker/Dockerfile (`FROM mcr.microsoft.com/dotnet/runtime:10.0.5-alpine3.23`, `ENV TZ=Europe/Berlin`) - Begründung: Lauffähiges Containerabbild.
- [PRIMÄR] deployment/WixSharpInstaller/ und src/webservice/Centron.Host.WindowsService/ - Begründung: Windows-Installationspfad.
- [KONTEXT] docs/guides/services/web-service-on-linux.md - Begründung: Betriebsanleitung für Linux.
Prüfidee: Identische Version in beiden Betriebsarten starten → gleicher Funktionsumfang, gleiche Datenbankkompatibilität.
Tracelinks: SyRS-057, SyRS-058, SwRS-042
Konsolidierung: nein
Status: belegt
```
```
ID: StRS-042
Titel: Automatisierte Datenbankaktualisierung bei Versionswechsel
Ebene: StRS
Typ: nicht-funktional (ISO 25010: Wartbarkeit)
Akteur: Betreiber / IT-Betrieb
Vorbedingung: Eine bestehende Datenbank einer älteren Version liegt vor.
Fakt: `ScriptEngineBL.ExecuteScripts` ermittelt alle noch nicht ausgeführten Skriptmethoden anhand der Tabelle `DBUpdate` (Abgleich über `ScriptNumber`), filtert sie gegen die aktuelle Anwendungsversion und führt sie in der Reihenfolge Version, Skriptnummer aus. Derzeit existieren 764 Skriptmethodenklassen unter `Administration/Scripts/ScriptMethods/Scripts/`.
Aussage: Das System soll das Datenbankschema bei einem Versionswechsel automatisch, idempotent und in definierter Reihenfolge auf den benötigten Stand bringen.
Ergebnis: Nach dem Start entspricht das Schema der Anwendungsversion; bereits ausgeführte Skripte werden nicht wiederholt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs, `ExecuteScripts` / `DoExecuteScriptMethodSet` (Abgleich gegen `dbUpdates`, Versionsfilter, geordnete Ausführung, Fehlerbehandlung mit `_scriptIgnoreIfErrorList`) - Begründung: Vollständig kodierter Migrationsmechanismus.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Scripts/ScriptMethods/Scripts/ (764 Dateien, höchste Nummer `ScriptMethod11820`) - Begründung: Umfang und Fortschreibung der Migrationshistorie.
- [KONTEXT] docs/guides/database/create-scripts.md, docs/reference/database/script-rules.md - Begründung: Regelwerk für neue Skripte.
Prüfidee: Migration zweimal hintereinander ausführen → beim zweiten Lauf wird kein Skript erneut ausgeführt.
Tracelinks: SyRS-059, SwRS-043
Konsolidierung: nein
Status: belegt
```
---
## 4. Abgrenzungen
- **Nicht Bestandteil dieser Spezifikation:** Anforderungen, die sich ausschließlich aus dem WPF-Bedienkonzept ergeben (Ribbonaufbau, Fensterlayout, Tastenkürzel). Für eine Web-/SaaS-Neuimplementierung sind sie nicht übertragbar.
- **Deaktivierte Funktionsbereiche:** Der Passwortmanager ist in der Modulregistrierung als "obsolate" (sic) gekennzeichnet; die Einstellungsseite des c-time-Connectors ist auf ausdrückliche fachliche Anweisung auskommentiert; das Reisekostenmodul ist als unfertig auskommentiert. Diese Bereiche sind in `Analysebericht.md` als Klärungsbedarf vermerkt.
@@ -0,0 +1,242 @@
# Traceability-Matrix
**System:** c-entron ERP-Suite
**Analysestand:** Commit `79c1142f48` (Branch `main`), 2026-08-25
**Zweck:** Forward- und Backward-Traceability zwischen StRS, SyRS und SwRS sowie Rückbindung an den jeweils tragenden Artefaktbeleg.
**Lesart der Tabelle:** Jede Zeile beschreibt eine Ableitungskette. Mehrere SwRS-IDs in einer Zeile bedeuten, dass die SyRS-Anforderung durch mehrere Softwareanforderungen realisiert wird. Der Artefaktbeleg nennt den für die Kette maßgeblichen Primärbeleg (Pfad relativ zum Wurzelverzeichnis der Codebasis).
---
## 1. Hauptmatrix (StRS → SyRS → SwRS)
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg |
|---|---|---|---|
| StRS-001 | SyRS-001 | SwRS-025 | `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs` |
| StRS-001 | SyRS-002 | SwRS-025 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` → `ValidateAppUser` |
| StRS-001 | SyRS-010 | SwRS-020 | `src/nexus/CentronNexus/Shared/Authorization/CentronAuthorization.cs` |
| StRS-002 | SyRS-005 | SwRS-022 | `src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs` |
| StRS-002 | SyRS-006 | SwRS-021 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CanUserEditReceipt` |
| StRS-002 | SyRS-007 | SwRS-045 | `src/backend/Centron.BL/Administration/AccessTokens/AccessTokenBL.cs` → `HashToken` |
| StRS-002 | SyRS-005 | SwRS-066 | `src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs` → `ModuleRegistrationItem.For<T>` |
| StRS-003 | SyRS-004 | SwRS-023 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` → `LicenseManager.CheckLicense` |
| StRS-003 | SyRS-004 | SwRS-066 | `src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs` → Lizenzausdrücke je Modul |
| StRS-004 | SyRS-014 | SwRS-024 | `src/backend/Centron.BL/Administration/Mandatory/MandatoryBL.cs` → `GetNumberGroup` |
| StRS-004 | SyRS-015 | SwRS-024, SwRS-060 | `src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs` → `GetNextNumber` |
| StRS-004 | SyRS-014 | SwRS-072 *(H)* | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` → nur `BranchI3D` |
| StRS-005 | SyRS-001 | SwRS-025, SwRS-044 | `src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs` → `SHA1Decoder` |
| StRS-005 | SyRS-003 | SwRS-026 | `src/backend/Centron.BL/Administration/Logins/TwoFactor/TwoFactorAuthBL.cs` |
| StRS-005 | SyRS-008 | SwRS-025 | `src/webservice/Centron.Controllers/Controllers/Unversioned/JwtAuthController.cs` |
| StRS-005 | SyRS-009 | SwRS-046, SwRS-073 *(H)* | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` → `_getExistingOrCreateTicketLock` |
| StRS-005 | SyRS-011 | SwRS-046 | `src/backend/Centron.BL/Administration/Logins/TicketBL.cs` → `GetExpireDate` |
| StRS-006 | SyRS-020 | SwRS-001, SwRS-002 | `src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| StRS-006 | SyRS-021 | SwRS-009 | `src/backend/Centron.BL/Sales/Receipts/Internal/AutomaticallyCloseReceiptHelperBL.cs` |
| StRS-006 | SyRS-060 | SwRS-048 | `tests/Centron.Tests.EndToEnd/Tests/SaveReceiptPerformance/SaveReceiptPerformanceTest.cs` |
| StRS-007 | SyRS-022 | SwRS-005 | `src/backend/Centron.BL/Sales/Receipts/*SpecificLogic.cs` → `CanBeForwardedInto()` |
| StRS-008 | SyRS-023 | SwRS-003, SwRS-004 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → Versionsprüfung |
| StRS-008 | SyRS-024 | SwRS-047 | `src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` → `ConcurrencyControlGuid` |
| StRS-009 | SyRS-024 | SwRS-006 | `src/backend/Centron.BL/Sales/Receipts/Invoices/ReceiptInvoiceBL.cs` → `CancelInvoice` |
| StRS-009 | SyRS-039 | SwRS-027 | `src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs` → `IsReceiptExported` |
| StRS-010 | SyRS-025 | SwRS-007 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CheckIfCustomerLimitIsReached` |
| StRS-011 | SyRS-026 | SwRS-008, SwRS-032 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CheckArticleMinPrices` |
| StRS-012 | SyRS-021 | SwRS-009 | `…/AutomaticallyCloseReceiptHelperBL.cs` → `ItemIsFinished` |
| StRS-013 | SyRS-027 | SwRS-010 | `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs` |
| StRS-013 | SyRS-028 | SwRS-006, SwRS-010 | `…/ReceiptInvoiceBL.cs` → `ResetContract` / `IsLastContractInvoice` |
| StRS-014 | SyRS-029 | SwRS-011 | `src/backend/Centron.BL/Sales/Receipts/ReceiptItemSpecialArticleHelperBL.cs` |
| StRS-015 | SyRS-030 | SwRS-012 | `src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs` → `IsSupplierReceipt()` |
| StRS-016 | SyRS-031 | SwRS-013 | `src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs` → `ApplyDistriToCentron` |
| StRS-017 | SyRS-032 | SwRS-014 | `src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptArticleBookingBL.cs` |
| StRS-017 | SyRS-032 | SwRS-071 *(H)* | `src/backend/Centron.BL/Warehousing/InventoryManagement/InventoryNewBL.cs` |
| StRS-018 | SyRS-033 | SwRS-015 | `src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptBarcodeBL.cs` |
| StRS-018 | SyRS-033 | SwRS-070 *(H)* | `src/backend/Centron.Entities/Entities/Warehousing/Barcode2/BarCode2.cs` |
| StRS-019 | SyRS-034 | SwRS-016 | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs` → `DoValidateMandatoryFields` |
| StRS-019 | SyRS-035 | SwRS-016 | `src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs` → `CloseHelpdesk` |
| StRS-019 | SyRS-040 | SwRS-020 | `src/backend/Centron.BL/Sales/Support/HelpdeskCloseBL.cs` → `SaveClosedTicketNotifications` |
| StRS-020 | SyRS-036 | SwRS-017 | `src/backend/Centron.BL/Administration/Logins/WebRightsVisibility.cs` |
| StRS-021 | SyRS-037 | SwRS-018 | `src/backend/Centron.BL/Sales/Receipts/Internal/ReceiptItemTimerBL.cs` |
| StRS-022 | SyRS-038 | SwRS-019 | `src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs` → Region „Abrechnung“ |
| StRS-022 | SyRS-028 | SwRS-010 | `src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs` |
| StRS-023 | SyRS-010 | SwRS-020 | `src/nexus/CentronNexus/Shared/Authorization/CentronAuthorization.cs` |
| StRS-023 | SyRS-061 | SwRS-049 | `src/nexus/CentronNexus.Host/appsettings.json` → `TicketCache` |
| StRS-023 | SyRS-062 | SwRS-049 | `src/nexus/CentronNexus.Host/appsettings.json` → `Upload` |
| StRS-023 | SyRS-071 | SwRS-020 | `…/CentronAuthorization.cs` → `PortHost` / `CustomerPortalPort` |
| StRS-024 | SyRS-041 | SwRS-020 | `src/backend/Centron.BL/Sales/Receipts/ReceiptCartReleaseSystemBL.cs` |
| StRS-025 | SyRS-042 | SwRS-020 | `src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs` |
| StRS-026 | SyRS-039 | SwRS-027 | `src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs` |
| StRS-027 | SyRS-043 | SwRS-028 | `src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs` |
| StRS-028 | SyRS-044 | SwRS-029 | `src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs` → `BlockNewReceiptsDunningLevel` |
| StRS-029 | SyRS-045 | SwRS-030 | `src/backend/Centron.BL/Finances/OnlineBanking/OnlineBankingAccountTransactionsBL.cs` |
| StRS-030 | SyRS-046 | SwRS-031 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `SaveProvision` |
| StRS-031 | SyRS-047 | SwRS-032 | `src/backend/Centron.BL/Warehousing/ActionPriceBL.cs` |
| StRS-032 | SyRS-048 | SwRS-033 | `src/apis/Centron.APIs.ITscopeDataAccess/ITscopeApi.cs` |
| StRS-033 | SyRS-049 | SwRS-034 | `src/apis/Centron.Api.Gls/CentronGlsLogic.cs`, `src/apis/Centron.Api.Shipcloud/CentronShipcloudLogic.cs` |
| StRS-034 | SyRS-050 | SwRS-035 | `src/backend/Centron.BL/CustomerArea/RmaBL.cs` |
| StRS-035 | SyRS-051 | SwRS-036 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `ConnectWithCrmProject` |
| StRS-036 | SyRS-052 | SwRS-037 | `src/backend/Centron.BL/Administration/Documents/Dsgvo/IOnlinePdfDocumentHandler.cs` |
| StRS-036 | SyRS-067 | SwRS-053 | `Directory.Build.props` → `DEV_BUILD`; `DeveloperSecurity.cs` |
| StRS-036 | SyRS-080 *(H)* | SwRS-037 | `src/backend/Centron.BL/Administration/Documents/Dsgvo/DsgvoBL.cs` |
| StRS-037 | SyRS-053 | SwRS-038 | `src/backend/Centron.BL/Sales/Receipts/IReceiptSpecificLogic.cs` → `CanCreateReport` |
| StRS-038 | SyRS-054 | SwRS-039 | `src/backend/Centron.BL/Accounts/TapiBL.cs` |
| StRS-039 | SyRS-055 | SwRS-040 | `src/backend/Centron.BL/Administration/Logins/Auth/Authenticator.cs` → `LocalizedStrings.*` |
| StRS-040 | SyRS-056 | SwRS-041 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → Audit-Zuweisungen |
| StRS-040 | SyRS-063 | SwRS-050 | `src/webservice/Centron.Host.WindowsService/nlog.config` |
| StRS-041 | SyRS-057 | SwRS-042 | `src/webservice/Centron.Host.WindowsService/`, `Centron.Host.Console/` |
| StRS-041 | SyRS-058 | SwRS-058 | `src/centron/Centron.WPF.UI/Services/Logics/**/{I,BL,WS}*Logic.cs` |
| StRS-041 | SyRS-065 | SwRS-052 | `src/backend/Centron.BL/Administration/WebServiceConfiguration/WebServiceConfig.cs` |
| StRS-041 | SyRS-066 | SwRS-052, SwRS-074 *(H)* | `…/WebServiceConfig.cs` → `DatabaseConnectionStringPlain`, `SecretKey` |
| StRS-041 | SyRS-070 | SwRS-042 | `docker/Dockerfile` |
| StRS-041 | SyRS-068 | SwRS-054, SwRS-055 | `src/webservice/Centron.Host/Services/ICentronRestService.cs`; `src/webservice/Centron.Controllers/Controllers/` |
| StRS-041 | SyRS-069 | SwRS-056, SwRS-063 | `src/webservice/Centron.Controllers/Configuration/GlobalExceptionFilter.cs` |
| StRS-041 | SyRS-081 *(H)* | SwRS-049, SwRS-052 | `src/nexus/CentronNexus.Host/appsettings.json` → `Host.Url` |
| StRS-042 | SyRS-059 | SwRS-043 | `src/backend/Centron.BL/Administration/Scripts/ScriptEngineBL.cs` |
| StRS-042 | SyRS-064 | SwRS-051 | `docs/Background Service/DataQualityService.md`; `DataQualityService` |
| StRS-042 | SyRS-072 | SwRS-057, SwRS-064 | `Directory.Build.props` → `TreatWarningsAsErrors`; `.github/workflows/` |
| StRS-042 | SyRS-073 | SwRS-057 | `Directory.Build.props` → `WarningsNotAsErrors` (NU1901–NU1904) |
| StRS-002 | SyRS-068 | SwRS-067 | `src/webservice/Centron.Host/Services/ICentronRestService.Obsolete.cs`; `UserRightsConst` `[Obsolete]` |
| StRS-034 | SyRS-050 | SwRS-035 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → `IReceiptClosedThroughRMA` |
| StRS-014 | SyRS-029 | SwRS-062 | `src/backend/Centron.Interfaces/Administration/Settings/SettingGroups/` |
| StRS-019 | SyRS-034 | SwRS-061 | `src/backend/Centron.BL/Administration/Settings/AppSettingsConst.cs` |
| StRS-027 | SyRS-043 | SwRS-061 | `src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs` |
| StRS-006 | SyRS-023 | SwRS-065 | `src/backend/Centron.DAO/Mappings/` |
| StRS-006 | SyRS-026 | SwRS-008 | `src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs` → Prüfkette |
*(H)* = Anforderung mit Status `HYPOTHESE` (siehe `Hypothesen.md`).
---
## 2. Rückwärtsindex SwRS → SyRS → StRS
| SwRS-ID | SyRS-ID | StRS-ID |
|---|---|---|
| SwRS-001 | SyRS-020 | StRS-006 |
| SwRS-002 | SyRS-020 | StRS-006 |
| SwRS-003 | SyRS-023 | StRS-008 |
| SwRS-004 | SyRS-023 | StRS-008 |
| SwRS-005 | SyRS-022 | StRS-007 |
| SwRS-006 | SyRS-024, SyRS-028 | StRS-009, StRS-013 |
| SwRS-007 | SyRS-025 | StRS-010 |
| SwRS-008 | SyRS-026 | StRS-011, StRS-006 |
| SwRS-009 | SyRS-021 | StRS-012, StRS-006 |
| SwRS-010 | SyRS-027, SyRS-028 | StRS-013, StRS-022 |
| SwRS-011 | SyRS-029 | StRS-014 |
| SwRS-012 | SyRS-030 | StRS-015 |
| SwRS-013 | SyRS-031 | StRS-016 |
| SwRS-014 | SyRS-032 | StRS-017 |
| SwRS-015 | SyRS-033 | StRS-018 |
| SwRS-016 | SyRS-034, SyRS-035 | StRS-019 |
| SwRS-017 | SyRS-036 | StRS-020 |
| SwRS-018 | SyRS-037 | StRS-021 |
| SwRS-019 | SyRS-038 | StRS-022 |
| SwRS-020 | SyRS-010, SyRS-040, SyRS-041, SyRS-042, SyRS-071 | StRS-001, StRS-019, StRS-023, StRS-024, StRS-025 |
| SwRS-021 | SyRS-006 | StRS-002 |
| SwRS-022 | SyRS-005 | StRS-002 |
| SwRS-023 | SyRS-004 | StRS-003 |
| SwRS-024 | SyRS-014, SyRS-015 | StRS-004 |
| SwRS-025 | SyRS-001, SyRS-008 | StRS-005, StRS-001 |
| SwRS-026 | SyRS-003 | StRS-005 |
| SwRS-027 | SyRS-039 | StRS-026, StRS-009 |
| SwRS-028 | SyRS-043 | StRS-027 |
| SwRS-029 | SyRS-044 | StRS-028 |
| SwRS-030 | SyRS-045 | StRS-029 |
| SwRS-031 | SyRS-046 | StRS-030 |
| SwRS-032 | SyRS-026, SyRS-047 | StRS-031, StRS-011 |
| SwRS-033 | SyRS-048 | StRS-032 |
| SwRS-034 | SyRS-049 | StRS-033 |
| SwRS-035 | SyRS-050 | StRS-034 |
| SwRS-036 | SyRS-051 | StRS-035 |
| SwRS-037 | SyRS-052 | StRS-036 |
| SwRS-038 | SyRS-053 | StRS-037 |
| SwRS-039 | SyRS-054 | StRS-038 |
| SwRS-040 | SyRS-055 | StRS-039 |
| SwRS-041 | SyRS-056 | StRS-040 |
| SwRS-042 | SyRS-057, SyRS-070 | StRS-041 |
| SwRS-043 | SyRS-059 | StRS-042 |
| SwRS-044 | SyRS-001 | StRS-005 |
| SwRS-045 | SyRS-007 | StRS-002 |
| SwRS-046 | SyRS-004, SyRS-009, SyRS-011 | StRS-003, StRS-005 |
| SwRS-047 | SyRS-024 | StRS-008 |
| SwRS-048 | SyRS-060, SyRS-072 | StRS-006, StRS-042 |
| SwRS-049 | SyRS-061, SyRS-062, SyRS-071 | StRS-023 |
| SwRS-050 | SyRS-063 | StRS-040 |
| SwRS-051 | SyRS-064 | StRS-042 |
| SwRS-052 | SyRS-065, SyRS-066 | StRS-041 |
| SwRS-053 | SyRS-067 | StRS-036 |
| SwRS-054 | SyRS-068 | StRS-041 |
| SwRS-055 | SyRS-068, SyRS-069 | StRS-041 |
| SwRS-056 | SyRS-069, SyRS-025 | StRS-041, StRS-010 |
| SwRS-057 | SyRS-072, SyRS-073 | StRS-042 |
| SwRS-058 | SyRS-058 | StRS-041 |
| SwRS-060 | SyRS-014, SyRS-015 | StRS-004 |
| SwRS-061 | SyRS-034, SyRS-043 | StRS-019, StRS-027 |
| SwRS-062 | SyRS-043, SyRS-062 | StRS-027, StRS-023 |
| SwRS-063 | SyRS-068, SyRS-069 | StRS-041 |
| SwRS-064 | SyRS-072 | StRS-042 |
| SwRS-065 | SyRS-023 | StRS-008, StRS-006 |
| SwRS-066 | SyRS-004, SyRS-005 | StRS-002, StRS-003 |
| SwRS-067 | SyRS-068 | StRS-002, StRS-003 |
| SwRS-070 *(H)* | SyRS-033 | StRS-018 |
| SwRS-071 *(H)* | SyRS-032 | StRS-017 |
| SwRS-072 *(H)* | SyRS-014 | StRS-004 |
| SwRS-073 *(H)* | SyRS-004, SyRS-009 | StRS-003, StRS-005 |
| SwRS-074 *(H)* | SyRS-066 | StRS-041 |
---
## 3. Abdeckungsübersicht
| Ebene | Anforderungen | davon `HYPOTHESE` | davon `Workaround` |
|---|---:|---:|---:|
| StRS | 42 | 0 | 2 |
| SyRS | 69 | 2 | 7 |
| SwRS | 71 | 5 | 22 |
| **Summe** | **182** | **7** | **31** |
*(Ermittelt durch Auszählen der Felder `ID:` bzw. `Status:` in den drei Spezifikationsdateien.)*
**Vergebene ID-Bereiche (mit bewussten Lücken)**
- StRS-001 … StRS-042 (lückenlos)
- SyRS-001 … SyRS-011, SyRS-014 … SyRS-015, SyRS-020 … SyRS-073, SyRS-080 … SyRS-081
- SwRS-001 … SwRS-058, SwRS-060 … SwRS-067, SwRS-070 … SwRS-074
Die Lücken entstanden durch die thematische Gliederung während der Formalisierung (Nummernblöcke je Themenbereich). Sie sind unschädlich, solange keine Nummer doppelt vergeben ist; dies wurde geprüft (siehe `Analysebericht.md`).
**Ableitungsdichte**
- Jede der 42 StRS-Anforderungen ist durch mindestens eine SyRS-Anforderung realisiert.
- Jede der 69 SyRS-Anforderungen verweist auf mindestens eine StRS-Anforderung und wird durch mindestens eine SwRS-Anforderung realisiert.
- Jede der 71 SwRS-Anforderungen verweist auf mindestens eine SyRS-Anforderung.
- Die Prüfung auf Verweise ins Leere (Tracelinks auf nicht existierende IDs) ist in `Analysebericht.md`, Abschnitt „Konsistenzcheck“, dokumentiert.
---
## 4. Konsolidierungskandidaten (Übersicht)
Anforderungen, deren Feld `Konsolidierung` einen Kandidaten nennt — d. h. dieselbe fachliche Funktion ist im Bestand mehrfach oder unterschiedlich implementiert.
| Kandidatengruppe | Beteiligte IDs | Fachlicher Kern | Empfehlung für das Zielsystem |
|---|---|---|---|
| Rechte vs. Lizenz | StRS-002, StRS-003, SwRS-066 | Modulverfügbarkeit wird in einem Ausdruck aus Recht und Lizenz bestimmt | Berechtigung und Produktumfang als getrennte Konzepte modellieren |
| Autorisierungsschichten | SyRS-005, SyRS-006, SyRS-010, SwRS-021 | Rechteprüfung an drei Stellen (API-Attribut, BL-Aufruf, Portalrichtlinie) | Eine Autorisierungsschicht mit einheitlichem Richtlinienmodell |
| Belegsichtbarkeit für Web-Accounts | StRS-001, StRS-023 | `ReceiptBL.CanUserViewReceipt` verweigert Web-Accounts pauschal, `WebAccountRightsConst` sieht Belegsichten vor | Eine Sichtbarkeitsregel je Belegart und Benutzerart |
| Einschränkende Rechte | StRS-002, StRS-020, SyRS-036 | „restricting rights“ existieren nur als Konvention | Eigener Rechtetyp mit definierter Auswertungsreihenfolge |
| Belegzustände | SyRS-020, SyRS-042 | `ReceiptState` und `WebReceiptState` als zwei unabhängige Zustandsräume | Ein Belegzustandsmodell mit Teilaspekten |
| Nebenläufigkeit bei Belegen | SyRS-024, SwRS-047 | Pessimistische Sperre und `ConcurrencyControlGuid` parallel | Auf ein Verfahren festlegen |
| Persistenzpfade Beleg | SwRS-003, SwRS-004, SwRS-065 | Sichtmodell und temporäre Legacy-Entitäten mit Repository | Ein Persistenzmodell je Beleg |
| Prüfkette im Speichervorgang | SyRS-026, SwRS-008 | Über 40 Prüfmethoden mit impliziter Reihenfolge in einer Klasse | Konfigurierbare, einzeln testbare Regelmenge |
| Preisfindung | StRS-011, StRS-031, SwRS-032 | Preisquellen ohne deklarierten Vorrang | Ein Preisfindungsdienst mit expliziter Vorrangregel |
| Abrechnungsmodelle | StRS-013, StRS-022, SwRS-019 | Drei Module erzeugen Rechnungen aus Leistungsdaten | Ein Abrechnungsdienst mit Strategien |
| Vertragslogik | SwRS-010 | Vier Komponenten mit überlappender Zuständigkeit | Klare Schnittzuordnung Beleg / Lebenszyklus / Abrechnung |
| Vorhabenmodelle | StRS-035, SwRS-036 | CRM-Projekt, Ticketprojekt, Taskmanagement, Belegprojekt-Layout | Ein Vorhabenmodell mit Ausprägungen |
| Protokollmodelle | StRS-040, SwRS-041 | Sieben parallele Änderungsprotokolle | Ein Auditmodell mit Objektreferenz |
| Benachrichtigungen | SyRS-040 | `Notifications` und `NexusNotifications` | Ein Benachrichtigungsmodell |
| Versandanbindungen | SyRS-049, SwRS-034 | GLS und Shipcloud ohne gemeinsame Abstraktion | Gemeinsame Versanddienstschnittstelle |
| Schnittstellengenerationen | SyRS-068, SwRS-054, SwRS-055 | 2.618 Altoperationen neben 160 modernen Endpunkten | Eine Schnittstellengeneration |
| Einstellungsregister | SwRS-061 | `Stammdat` (728) und `ApplicationSettings` (491) | Ein Register, Altbestand migrieren und entrümpeln |
| Konfigurationsmodelle | SwRS-049, SwRS-052 | `WebServiceConfig`, `appsettings.json`, Verbindungsdateien | Ein Konfigurationsmodell mit Geheimnisspeicher |
| Protokollkonfigurationen | SyRS-063, SwRS-050 | Vier NLog-Konfigurationen mit abweichenden Werten | Gemeinsame Vorgabe für Stufe, Format, Aufbewahrung |
| Meldungsherkunft | StRS-039, SyRS-055, SwRS-040 | Ressourcen und hart kodierte Texte gemischt | Ausschließlich Ressourcenschlüssel |
| Doppelter Datenzugriff | SyRS-058, SwRS-058 | `BL*Logic` und `WS*Logic` je Fachschnittstelle | In der Web-Zielarchitektur entfällt der Direktzugriffspfad |
| E-Rechnung | SyRS-043, SwRS-028 | Eigenentwicklung statt Standardbibliothek | Standardbibliothek einsetzen |
| Barcodemodelle | SwRS-015, SwRS-070 | `BarCode` und `BarCode2` | Auf ein Modell reduzieren |
| Inventurmodelle | SwRS-014, SwRS-071 | `InventoryBL` und `InventoryNewBL` | Auf eine Implementierung reduzieren |
| Exportsperre | SyRS-039 | Sperre gegen Storno nur für Rechnungen implementiert | Regel für alle exportierten Belegarten prüfen |
| Ablageorte | SwRS-021, SwRS-039 | `EntitiesWrongPlace`, `TapiBL` unter `Accounts/` | Domänenkonforme Ablage |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 20 (Lauf N)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T20:00:07+02:00
- **Endzeit:** 2026-08-25T20:59:56+02:00
- **Dauer gesamt:** 00:59:49 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:59:48 (`duration_ms`) — API: 00:58:05
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-26d8`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-f63e`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 212
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/21 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 200 |
| Output-Tokens | 315.006 (davon 14.034 Thinking-Tokens) |
| Cache-Write-Tokens | 499.299 |
| Cache-Read-Tokens | 23.461.564 |
| Agent-Turns | 145 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 200 | 4.192 | 4.392 |
| Output-Tokens | 315.006 | 21 | 315.027 |
| Cache-Write-Tokens | 499.299 | 0 | 499.299 |
| Cache-Read-Tokens | 23.461.564 | 0 | 23.461.564 |
| Tokens gesamt | 24.276.069 | 4.213 | **24.280.282** |
**Tokens gesamt: 24.280.282** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `3aa8eb7c-721a-4061-91d6-b92484c00cfb`
- **Permission-Denials:** **0** – —
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 83.882 B | 42 Anforderungen |
| `SyRS.md` | 124.119 B | 69 Anforderungen |
| `SwRS.md` | 127.467 B | 71 Anforderungen |
| `Traceability.md` | 19.416 B | 88 Datenzeilen |
| `Hypothesen.md` | 11.012 B | 17 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 12.627 B | Domänenbegriffe |
| `Analysebericht.md` | 25.360 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **182 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 42 | 23,1 % |
| SyRS | 69 | 37,9 % |
| SwRS | 71 | 39,0 % |
| **Gesamt** | **182** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 75 | 41,2 % |
| Sicherheit | 32 | 17,6 % |
| Daten | 24 | 13,2 % |
| Schnittstelle | 23 | 12,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit — Analysierbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit — Testbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Sicherheit — Nachweisbarkeit) | 2 | 1,1 % |
| nicht-funktional (ISO 25010: Übertragbarkeit) | 2 | 1,1 % |
| nicht-funktional (ISO 25010: Zuverlässigkeit — Fehlertoleranz) | 2 | 1,1 % |
| (10 weitere) | 13 | 7,1 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 485 |
| davon `PRIMÄR` | 341 (70,3 %) |
| davon `SEKUNDÄR` | 66 (13,6 %) |
| davon `KONTEXT` | 78 (16,1 %) |
| Belege je Anforderung (Median) | 3,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 182 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 174 | 95,6 % |
| als `HYPOTHESE` gekennzeichnet | 8 | 4,4 % |
| als Workaround vermerkt | 31 | 17,0 % |
| Konsolidierungskandidaten | 55 | 30,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (51 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 182 von 182 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(212 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":3484745,"num_turns":145,"stop_reason":"end_turn","session_id":"3aa8eb7c-721a-4061-91d6-b92484c00cfb","total_cost_usd":24.604218999999997,"usage":{"input_tokens":200,"cache_creation_input_tokens":499299,"cache_read_input_tokens":23461564,"output_tokens":315006,"output_tokens_details":{"thinking_tokens":14034},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":499299,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1385,"cache_read_input_tokens":475998,"cache_creation_input_tokens":1337,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":1337},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":21,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0042970000000000005,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":200,"outputTokens":315006,"cacheReadInputTokens":23461564,"cacheCreationInputTokens":499299,"webSearchRequests":0,"costUSD":24.599921999999996,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Alle sieben Ergebnisdateien liegen unter `…\\01_Lauf_2026-08-25_195917_opus5_solo_v3.6.0-26d8\\Ergebnisse\\`; das Arbeitsverzeichnis der Codebasis ist unverändert (`git status` leer).\n\n## Ergebnis\n\n**182 Anforderungen** über drei Ebenen: StRS 42, SyRS 69, SwRS 71 — jede mit `Fakt`/`Aussage`-Trennung, Belegen, Prüfidee, Tracelinks und Konsolidierungsvermerk.\n\n**Belegbasis:** 485 Belege, davon 341 `PRIMÄR` (70,3 %), 66 `SEKUNDÄR`, 78 `KONTEXT` — im Mittel 2,66 Belege je Anforderung.\n\n**Konsistenzcheck (automatisiert über alle vier Dateien):** keine doppelten IDs, keine Anforderung ohne Beleg, **keine Anforderung ohne `PRIMÄR`-Beleg** (damit ist die verschärfte Evidenzvorgabe für die 32 Sicherheits- sowie alle Fakturierungs- und Berechtigungsanforderungen ausnahmslos erfüllt), keine Anforderung ohne Prüfidee, keine Tracelinks ins Leere, vollständige Abdeckung in beiden Richtungen der Traceability-Matrix.\n\n**7 Hypothesen (3,8 %)** mit fehlender Information, Klärungsweg und Priorisierung — die architekturbestimmende ist H-03: Belegköpfe tragen `BranchI3D`, aber keinen Mandantenschlüssel, und Nummernkreise laufen ausdrücklich über den Standardmandanten. Für ein SaaS-Ziel ist damit eine Mandantentrennung neu zu entwerfen.\n\n**31 Anforderungen mit Status `belegt; Workaround`**, u. a. die ungesalzene SHA-1-Kennwortablage (`// TODO the password should be salted!!!`), die erneute Passwortabfrage im Belegspeichervorgang bei Mindestpreisunterschreitung, Belegvorlagen als negative Belegnummer und `NU1901–NU1904` als nicht-fehlerhafte Buildwarnungen.\n\n**26 Konsolidierungskandidaten** in `Traceability.md`, Abschnitt 4 — größte Hebel: 2.618 Alt-REST-Operationen neben 160 modernen Endpunkten, 1.219 Einstellungswerte in zwei Registern, doppelte Persistenzpfade je Beleg, `BL*Logic`/`WS*Logic`-Doppelimplementierung, sieben Protokollmodelle.\n\n## Zwei Punkte zur Einordnung\n\nDie Analyse ist **nicht vollständig**. Rund 20 Fachbereiche (Produktion, MSP, Kampagnen, Checklisten, Exchange-Sync, Asset-Management mit über 100 Objektarten u. a.) sind in `Analysebericht.md` Abschnitt 5.1 als Tiefe **D** ausgewiesen — dafür wurden bewusst keine Anforderungen erhoben, statt sie dünn zu belegen. Ebenso liegt **keine DDL im Arbeitsverzeichnis** (0 `.sql`-Dateien); das Schema entsteht zur Laufzeit aus 764 Skriptmethoden, weshalb kein Constraint als Beleg dienen konnte.\n\nEine ursprünglich als Hypothese formulierte Aussage (Sitzungstickets ohne Gültigkeitsgrenze) habe ich beim Gegenlesen von `TicketBL.cs` widerlegt und als belegte Anforderung SyRS-011 aufgenommen; der Vorgang ist in `Hypothesen.md` als Nachtrag dokumentiert.","ttft_ms":2622,"ttft_stream_ms":1800,"time_to_request_ms":43,"type":"result","duration_ms":3587576,"uuid":"fd1de15b-57e6-463f-8976-71a495ea5203","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 42 | 23,1 % |
| SyRS | 69 | 37,9 % |
| SwRS | 71 | 39,0 % |
| **Gesamt** | **182** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 75 | 41,2 % |
| Sicherheit | 32 | 17,6 % |
| Daten | 24 | 13,2 % |
| Schnittstelle | 23 | 12,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit — Analysierbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Wartbarkeit — Testbarkeit) | 3 | 1,6 % |
| nicht-funktional (ISO 25010: Sicherheit — Nachweisbarkeit) | 2 | 1,1 % |
| nicht-funktional (ISO 25010: Übertragbarkeit) | 2 | 1,1 % |
| nicht-funktional (ISO 25010: Zuverlässigkeit — Fehlertoleranz) | 2 | 1,1 % |
| (10 weitere) | 13 | 7,1 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 485 |
| davon `PRIMÄR` | 341 (70,3 %) |
| davon `SEKUNDÄR` | 66 (13,6 %) |
| davon `KONTEXT` | 78 (16,1 %) |
| Belege je Anforderung (Median) | 3,0 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 182 (100,0 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 174 | 95,6 % |
| als `HYPOTHESE` gekennzeichnet | 8 | 4,4 % |
| als Workaround vermerkt | 31 | 17,0 % |
| Konsolidierungskandidaten | 55 | 30,2 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (51 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 182 von 182 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195917_opus5_solo_v3.6.0-26d8\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:59:56.6053313+02:00
@@ -0,0 +1 @@
2026-08-25T20:00:07.2059112+02:00
@@ -0,0 +1,327 @@
# Analysebericht
**System:** NEXOWARE c-entron ERP-Suite (c-entron.NET / c-entron Nexus)
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse (keine Ausführung)
**Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server (V1 Baseline, Prompt-only)
**Codebasis:** `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Zweig `main`, HEAD `79c1142f48`
**Ausgabeverzeichnis:** `…\01_Lauf_2026-08-25_195918_opus5_solo_v3.6.0-f63e\Ergebnisse\`
**Erstellt:** 2026-08-25
**Änderungen an der Codebasis:** keine (ausschließlich lesende Zugriffe)
---
## 1. Untersuchungsgegenstand
### 1.1 Mengengerüst
| Kennzahl | Wert | Ermittlung |
|---|---|---|
| Projekte in `Centron.sln` | 82 | `grep -c "^Project(" Centron.sln` |
| C#-Quelldateien (ohne `obj`/`bin`) | 14.690 unter `src/`+`tests/`, 14.782 im gesamten Baum | `find … -name "*.cs" -not -path "*/obj/*" -not -path "*/bin/*"` |
| C#-Quellzeilen unter `src/` (roh, inkl. Leer- und Kommentarzeilen) | rund 1.667.000 | `find src -name "*.cs" … -exec cat {} + \| wc -l` |
| XAML-Dateien | 1.233 | `find src -name "*.xaml" -not -path "*/obj/*"` |
| Razor-Komponenten | 491 | `find src -name "*.razor" -not -path "*/obj/*"` |
| Entwicklerdokumente (`docs/`) | 44 Markdown-Dateien | `find docs -name "*.md"` |
| Datenbank-Migrationsskripte | 764 (`ScriptMethod11820` als höchste Nummer) | `ls .../ScriptMethods/Scripts/` |
| Legacy-REST-Methoden | 1.279 (`[WebInvoke(Method="POST"…)]`) | `grep -rn` über `CentronRestServiceInterfaceParts/` |
| Anwendungseinstellungen | Nächste freie ID 10471 (aktuelle Tabelle) plus historische `Stammdat`-Einstellungen | Kopfkommentar `ApplicationSettingID.cs` |
| Rechtekatalog | `UserRightsConst.cs` mit 2.819 Zeilen, nächste freie ID 20800174 | Kopfkommentar `UserRightsConst.cs` |
| Commits gesamt | 52.135 | `git rev-list --count HEAD` |
| Beitragende (Top-Autor) | Daniel Häfele (5.603 Commits) | `git shortlog -sn` |
| Produktversion | `2.0.2611-alpha` (Nerdbank.GitVersioning) | `version.json` |
| Zielplattform | .NET SDK 10.0.100 | `global.json` |
### 1.2 Projektlandschaft und Dateiumfang je Projekt
| Projekt | Dateien (cs/xaml/razor) | Rolle |
|---|---|---|
| `src/centron/Centron.WPF.UI` | 6.321 | WPF-Desktop-Client (DevExpress), Hauptbedienoberfläche |
| `src/webservice/Centron.WebServices.Core` | 2.530 | Legacy-REST-Vertrag, DTOs, Rechtekataloge |
| `src/backend/Centron.BL` | 2.068 | Geschäftslogik |
| `src/nexus/CentronNexus` | 1.222 | Blazor-Server-Portal (ServiceBoard + Kundenportal) |
| `src/backend/Centron.Entities` | 1.185 | NHibernate-Entitäten |
| `src/backend/Centron.DAO` | 1.131 | Mappings, DAOs, benannte Abfragen |
| `src/shared/Centron.Controls` | 1.031 | Wiederverwendbare UI-Steuerelemente |
| `src/backend/Centron.Interfaces` | 764 | Schnittstellen, Aufzählungen, DTO-Verträge |
| `src/webservice/Centron.Host` | 158 | REST-Host, `CentronRestService` (35 Teilklassen) |
| `src/centron/Centron.WPF.UI.Extension` | 160 | Modulschnittstellen für Erweiterungen |
| `src/backend/Centron.Gateway` | 105 | Gateway-Komponente |
| `src/nexus/CentronNexus.OutlookAddIn` | 88 | Outlook-Add-in |
| `src/shared/Centron.Core` | 74 | Basishilfsklassen |
| `src/apis/*` (8 Projekte) | 201 gesamt | Fremdsystemanbindungen (FinAPI 72, Shipcloud 32, ITscope 24, EGIS 20, GLS 17, COP 16, Icecat 16, eb-Interface 4) |
| `src/webservice/Centron.Controllers` | 57 | ASP.NET-Core-Controller (v1 + Unversioned) |
| `src/backend/Centron.Common` | 58 | Gemeinsame Hilfsklassen |
| `src/shared/Centron.Controls.Preview` | 58 | Vorschaukomponenten |
| `src/webservice/c-entron.misc.ConnectionManager` | 47 | Verbindungsverwaltung |
| `tests/*` (13 Projekte) | — | Unit, DAO, Integration, End-to-End, Playwright, Nexus, API |
### 1.3 Geschäftslogik nach Fachbereich (`Centron.BL`)
| Fachbereich | Dateien | Analysetiefe (siehe Abschnitt 3) |
|---|---|---|
| `Administration` (inkl. Scripts, Logins, Licensing, Settings, Rights, DataSecurity) | 959 | teilweise tief (Logins, Licensing, Settings, Rights, Scripts), sonst stichprobenhaft |
| `WebServices` (WebServiceBL-Schicht, ObjectMapper) | 464 | stichprobenhaft |
| `Sales/Receipts` | 117 | tief |
| `Sales/Support` (Helpdesk) | 53 | tief |
| `Sales/CustomerAssets` (Verträge, Abrechnung, TimerBilling) | 41 | tief (Vertragsabrechnung), sonst stichprobenhaft |
| `Warehousing` | 40 | stichprobenhaft |
| `EDI` | 27 | oberflächlich |
| `ReportEngine` | 26 | oberflächlich |
| `ArtificialIntelligence` | 25 | nicht analysiert |
| `DataExchange` | 23 | stichprobenhaft (BookKeeping), sonst oberflächlich |
| `Statistics` | 16 | oberflächlich |
| `Finances` | 9 | oberflächlich |
| `Production`, `PasswordManager`, `Calendar`, `Tapi`, `Mobile` | je 1–2 | nicht analysiert |
---
## 2. Vorgehen (RRE-Schritte 2–6)
**Schritt 1 (Scope)** war vorgegeben: gesamte Codebasis, keine Modulbeschränkung, eigenständige Priorisierung
der Analysetiefe.
**Schritt 2 — Artefakterhebung.** Erfasst wurden: Projektstruktur und Lösungsdatei; die
Entwicklerdokumentation unter `docs/` (44 Dokumente, davon 11 vollständig gelesen); `README.md` und
`CentronRights.md`; Build- und Versionskonfiguration (`Directory.Build.props`, `global.json`, `version.json`,
`DevExpress.Version.props`); Betriebsartefakte (`docker/Dockerfile`, `azure/*.yml`, `nlog.config`,
`appsettings.json`); Quellcode der Geschäftslogik, Entitäten, Mappings, Schnittstellen, Controller,
Blazor-Komponenten und Modulregistrierung; die Git-Historie (52.135 Commits, Auswertung der letzten 40
Commit-Titel und der Autorenverteilung).
**Schritt 3 — Technische Analyse.** Identifiziert wurden: die vier Teilsysteme und ihre Schichtung; die
Modullandschaft über `ModuleRegistration.cs` (rund 70 registrierte Module mit je Rechte- und
Lizenzbedingung); die Zustandsmaschinen `ReceiptState`, `ReceiptCartState`, `WebReceiptState` und der
datengetriebene Ticketstatus; die Validierungslogik in `ReceiptBL.SaveReceipt` und `HelpdeskBL.Save`; die
Berechtigungsprüfungen in `Authenticator`, `ReceiptBL`, `HelpdeskBL`, `HelpdeskTimerBL`,
`ReceiptCartReleaseSystemBL` und `CentronAuthorization`.
**Schritt 4 — Semantische Interpretation.** Aus technischen Befunden wurden fachliche Aussagen abgeleitet,
z. B.: aus `dunningLevel >= blockOnLevel` → Kreditsperre als Geschäftsregel (SyRS-22); aus den drei
Zuordnungsfeldern in `HelpdeskTimer` → Abrechnungsschutz erfasster Leistungen (SyRS-31); aus
`ExpirationKind` je `ApplicationKind` → anwendungsabhängige Sitzungsdauer (SyRS-05). Die technische
Beobachtung steht in jeder Anforderung getrennt im Feld `Fakt`, die Interpretation im Feld `Aussage`.
**Schritt 5 — Formalisierung.** 109 Anforderungen im vorgegebenen Format mit Vorbedingung, Fakt, Aussage,
Ergebnis und Prüfidee.
**Schritt 6 — Traceability-Anreicherung.** 394 Einzelbelege mit Pfad, Klasse/Methode und Begründung; Forward-
und Backward-Verknüpfung über alle drei Ebenen in `Traceability.md`.
**Schritt 7 (Validierung)** erfolgt manuell durch Fachexperten; `Hypothesen.md` ist dafür die Arbeitsgrundlage.
---
## 3. Analysetiefe je Bereich
Die Priorisierung folgte drei Kriterien: (a) fachlicher Kern des ERP (Beleg, Vertrag, Ticket, Zeit),
(b) sicherheits- und abrechnungsrelevante Bereiche gemäß der geforderten risikobasierten Priorisierung,
(c) migrationskritische Querschnittsthemen (Architektur, Persistenz, Konfiguration, Betrieb).
### 3.1 Tief analysiert (Datei vollständig oder in relevanten Abschnitten gelesen)
| Bereich | Gelesene Artefakte | Abgeleitete Anforderungen |
|---|---|---|
| Authentifizierung, Sitzung, Lizenz | `Authenticator.cs`, `BasicAuthenticator.cs`, `AuthenticatorFactory.cs`, `TicketBL.cs`, `LicenseManager.CheckLicense`, `ApplicationKind.cs`, `CryptoUtils.cs`, `UsersBL` (Passwortteil), `JwtAuthController.cs`, `AUTHENTICATION.md` | SyRS-01…08, SyRS-44, SwRS-11…13 |
| Belegwesen | `ReceiptBase.cs`, `ReceiptState.cs`, `CentronObjectKindNumeric.cs`, `ReceiptBL.cs` (Methodenübersicht + rund 700 gezielt gelesene Zeilen: Rechteprüfung, Versionierung, Pflichtfelder, Steuernummer, Report, Signatur), `ReceiptProgressionBL.cs`, `InvoiceSpecificLogic.cs` (Rechte/Einstellungen) | SyRS-11…26, SwRS-04, SwRS-15…17 |
| Helpdesk | `HelpdeskBL.cs` (Rechteprüfung, Speicherablauf, Historisierung), `HelpdeskCloseBL.cs`, `HelpdeskTimerBL.cs` (Löschregel), `HelpdeskState.cs`, `HelpdeskStateBaseMaps.cs`, `HelpdeskTimer.cs`, `CentronRights.md` | SyRS-27…31, SwRS-19, SwRS-20 |
| Vertragsabrechnung | `AutomaticFacturaBL.cs`, `AutomaticFacturaBL.Contracts.cs` (Intervall-/Kontingentlogik), zehn Aufzählungen unter `BillingCenter/Contracts/` | SyRS-32, SyRS-33, SwRS-21 |
| Warenkorb-Freigabe | `ReceiptCartState.cs`, `ReceiptCartReleaseSystemBL.cs` | SyRS-34, SwRS-18 |
| Rechte- und Lizenzmodell | `UserRightsConst.cs` (Kopf + Struktur), `WebAccountRightsConst.cs`, `ModuleRegistration.cs` (954 Zeilen vollständig), `CentronAuthorization.cs`, `check-userrights.md`, `add-a-new-right.md`, `licensing-system.md` | SyRS-09, SyRS-10, SyRS-35, SwRS-09…11, SwRS-24, SwRS-30, SwRS-31 |
| Persistenz und Konventionen | `BaseEntity.cs`, `DBEntity.cs`, `BaseMaps.cs`, `ChangeLogMaps.cs`, `NumberGroupBL.cs`, `database-conventions.md`, `dtos-and-entities.md` | SyRS-13, SyRS-14, SyRS-37, SwRS-05…07, SwRS-14, SwRS-36 |
| Betrieb und Auslieferung | `Dockerfile`, `build-pipeline.yml`, `tests-pipeline.yml`, `analyze-pipeline.yml`, `nlog.config`, `appsettings.json`, `Directory.Build.props`, `create-scripts.md`, `DataQualityService.md` | SyRS-39…43, SwRS-23, SwRS-26, SwRS-28, SwRS-33, SwRS-35 |
### 3.2 Stichprobenhaft analysiert (Struktur und Schlüsselstellen, nicht vollständig)
| Bereich | Was geprüft wurde | Was offen blieb |
|---|---|---|
| Buchhaltungsexport | Methodenübersicht `BookKeepingExportBL.cs`, Testprojekte für DATEV XML Online 2020 und Abacus | Feldzuordnungen je Format, Kontenfindung |
| ZUGFeRD/XRechnung | Dateiliste, `GetLeitwegID`/`GetLocalZUGFeRDSetting`, Abbruchbedingung, Doku, Test | Feldabbildung, unterstützte Profile |
| Warenwirtschaft | Methodenübersicht `ArticleStockBL.cs`, Verzeichnisstruktur Inventur/Kommissionierung | Buchungslogik der Bestandsveränderung, Bewertungsverfahren |
| Einkauf | Entitätsstruktur der vier Lieferantenbelegarten, Dublettenprüfung | Bestellvorschlag, EDI-Bestellabwicklung |
| DSGVO | `DataSecurityBL.cs` (Methodenübersicht, Löschvermerke, Transaktionsklammer) | Vollständigkeit des Löschumfangs (siehe H-08) |
| Nexus-Portal | Seitenstruktur, Autorisierungsmodell, Konfigurationsklassen, `AUTHENTICATION.md` | Fachlogik der einzelnen Portalseiten |
| REST-Schnittstellen | Struktur beider Generationen, `AuthenticateAttribute`, `add-webservice-methods.md` | Fachliche Semantik der 1.279 Legacy-Methoden |
| Provision | Entitätsmodell, Automatikeinstellungen in `InvoiceSpecificLogic` | Berechnungsformel der Provisionsschemata |
| Mahnwesen/OPOS | Sperrlogik in `ReceiptBL`, Modul- und Verzeichnisstruktur | Mahnstufenfortschreibung, Mahnlauf, Zinsen/Gebühren |
### 3.3 Nur verortet, keine Anforderungen abgeleitet
Produktionsplanung; Passwort-Manager; MSP-Collector/-Auswertung; EDI im Detail; Kalender und
Exchange-Synchronisation; TAPI/Telefonie; KI-Assistenz; Mobile/Außendienst; Dokumentations-Assistent;
Reportengine; Online-Banking/FinAPI; Massenaktualisierung; Checklisten und C-FLOW-Ticketvorlagen;
Inventur im Detail; RMA im Detail (nur Nummernkreise und Belegverkettung erfasst).
Diese Bereiche sind in `Hypothesen.md`, Abschnitt C, einzeln mit Verortung und offener Frage aufgeführt.
### 3.4 Nicht analysierbar (außerhalb des Untersuchungsgegenstands)
- **c-entron Delphi.** Der Code verweist an mindestens vier Stellen auf eine parallel betriebene
Delphi-Anwendung, die Teile der Fachlichkeit trägt (Objektartvergabe, Kunden-/Lieferantenanlage bei
deaktiviertem `IsAccountManagementActive`, Rechtefelder `FomName`/`FomCont`, eigene Versionslinie 9.3.x).
Dieser Anteil liegt nicht als Datei im Arbeitsverzeichnis vor. Siehe Hypothese H-11.
- **Datenbankschema.** Es liegen keine `.sql`-Dateien im Repository (`find . -name "*.sql"` → 0 Treffer).
Das Schema wurde ausschließlich aus den Fluent-NHibernate-Mappings und den Migrationsskripten abgeleitet;
Indizes, Constraints und Trigger der Produktivdatenbank sind damit **nicht** belegt.
- **Lizenzserver.** Die tatsächlichen Lizenzinhalte (Anzahl, Gültigkeit) liegen laut
`licensing-system.md` auf einem externen Lizenzserver.
- **Ticketsystem und Excel-Skriptnummernliste.** Commit-Titel verweisen auf Ticketnummern
(z. B. "Ticket 168496"); das Ticketsystem selbst war nicht zugänglich. Die Skriptnummernreservierung
erfolgt laut `create-scripts.md` in einer Excel-Datei in Microsoft Teams.
---
## 4. Konsistenzcheck über das gesamte Anforderungs-Set
Der Check wurde maschinell über die drei Spezifikationsdateien ausgeführt (Auswertung aller Blöcke mit
`ID:`-Zeile).
| Prüfung | Ergebnis |
|---|---|
| Anforderungsblöcke gesamt | 109 (StRS 26, SyRS 47, SwRS 36) |
| **Doppelte oder mehrfach vergebene IDs** | **keine** |
| **Anforderungen ohne Beleg** | **keine** — jede Anforderung führt mindestens einen klassifizierten Beleg mit Begründung |
| **Anforderungen ohne `PRIMÄR`-Beleg** | **1** — SwRS-34; diese ist folgerichtig als `HYPOTHESE` gekennzeichnet |
| **Tracelinks auf nicht existierende IDs** | **keine** (nach Korrektur von vier Fehlverweisen, siehe unten) |
| Anforderungen ohne `Tracelinks`-Feld | keine |
| Belege gesamt | 394 |
| Belegverteilung gesamt | `PRIMÄR` 278 (70,6 %), `SEKUNDÄR` 52 (13,2 %), `KONTEXT` 64 (16,2 %) |
| Belegverteilung StRS | `PRIMÄR` 68, `SEKUNDÄR` 19, `KONTEXT` 14 (Summe 101) |
| Belegverteilung SyRS | `PRIMÄR` 114, `SEKUNDÄR` 22, `KONTEXT` 20 (Summe 156) |
| Belegverteilung SwRS | `PRIMÄR` 96, `SEKUNDÄR` 11, `KONTEXT` 30 (Summe 137) |
| Statusverteilung | `belegt` 83, `belegt; Workaround` 25, `HYPOTHESE` 1 |
| Anforderungen mit Konsolidierungskandidat | 29, gebündelt zu 13 Konsolidierungsgruppen (K-1…K-13 in `Traceability.md`) |
### 4.1 Während des Checks behobene Befunde
| Befund | Betroffen | Korrektur |
|---|---|---|
| Tracelink auf sachfremde ID (DSGVO verwies auf die Uploadbegrenzung) | StRS-20 | Neue Anforderung SyRS-45 (DSGVO-Löschen) ergänzt, Verweis korrigiert |
| Tracelink auf sachfremde ID (C-Sign verwies auf die Lizenzprüfung) | StRS-22 | Neue Anforderung SyRS-46 (Web-Beleg-Freigabestatus) ergänzt, Verweis korrigiert |
| Tracelink auf sachfremde ID (externe Systeme verwiesen auf Pflichtfelder) | StRS-23 | Neue Anforderung SyRS-47 (Konnektorkonfiguration) ergänzt, Verweis korrigiert |
| Tracelink zeigte auf die Belegprogression statt auf die Belegprüfmethoden | StRS-15 | Verweis auf SwRS-15 korrigiert |
| `PRIMÄR`-Beleg für eine nicht gelesene Datei geführt | SwRS-34 | Auf `KONTEXT` herabgestuft; Status bleibt `HYPOTHESE`, offene Frage in H-01 dokumentiert |
### 4.2 Einhaltung der risikobasierten Evidenzanforderung
Die verschärfte Evidenzregel (mindestens ein `PRIMÄR`-Beleg für Sicherheitsregeln, Abrechnungs- und
Fakturierungslogik sowie Berechtigungen, andernfalls `[HYPOTHESE]`) ist eingehalten:
- **Sicherheit** (SyRS-01…08, 10, 20, 21, 35, 36, 44, 45; SwRS-09…13, 15, 24, 34): alle mit `PRIMÄR`-Beleg
außer SwRS-34, das folgerichtig als `HYPOTHESE` geführt wird.
- **Abrechnung/Fakturierung** (StRS-06, 07, 10, 13, 14, 15, 18; SyRS-22…26, 31…33; SwRS-21, 22): alle mit
mindestens einem `PRIMÄR`-Beleg aus Geschäftslogik oder Aufzählungsdefinition.
- **Berechtigungen** (StRS-02, 11, 19; SyRS-09, 10, 20, 21, 28; SwRS-09, 10, 30, 31): alle mit
`PRIMÄR`-Beleg aus der serverseitigen Durchsetzung, nicht nur aus der Oberfläche.
---
## 5. Selbstbewertung
### 5.1 Vollständigkeit der Modulabdeckung
| Kategorie | Bereiche |
|---|---|
| **Vollständig analysiert** | Kein Bereich. Der Umfang (14.690 Quelldateien, 82 Projekte) macht eine erschöpfende Analyse in einem Lauf unmöglich; „vollständig“ wäre eine unbelegbare Behauptung. |
| **Tief analysiert** (Kernlogik gelesen, Regeln belegt) | Authentifizierung/Sitzung/Lizenz · Belegwesen (Kern) · Helpdesk (Kern) · Zeiterfassung · Vertragsabrechnung · Warenkorb-Freigabe · Rechte-/Lizenzmodell · Persistenzkonventionen · Nummernkreise · Betrieb/Auslieferung |
| **Stichprobenhaft** | Buchhaltungsexport · ZUGFeRD · Warenwirtschaft · Einkauf · DSGVO · Nexus-Portal · REST-Schnittstellen · Provision · Mahnwesen |
| **Nur verortet** | 14 Bereiche, siehe `Hypothesen.md` Abschnitt C |
| **Nicht analysierbar** | c-entron Delphi · produktives Datenbankschema · Lizenzserver · Ticketsystem |
Geschätzte Abdeckung: Die Anforderungen decken den **transaktionalen Kern** (Beleg, Vertrag, Ticket, Zeit,
Berechtigung, Anmeldung) belastbar ab. Gemessen an der Zahl der registrierten Module (rund 70) sind etwa
20 Module durch mindestens eine Anforderung inhaltlich vertreten; die übrigen sind zwar über StRS-03
(Lizenzmodell) und SyRS-09 (Modulsichtbarkeit) formal erfasst, aber fachlich nicht spezifiziert.
### 5.2 Stellen mit dünner Belegbasis
Der Anteil an `PRIMÄR`-Belegen liegt insgesamt bei 70,6 %. Dünn ist die Belegbasis dort, wo der Anteil an
`KONTEXT`-Belegen (Dokumentation, Kommentare) den Ausschlag gibt:
| Anforderung | Problem | Bewertung |
|---|---|---|
| SwRS-34 Entwicklerschutz | ausschließlich `KONTEXT` (Herstellerdoku) | als `HYPOTHESE` gekennzeichnet — korrekt behandelt |
| SyRS-40 Hintergrunddienst Datenqualität | führender Beleg ist `docs/Background Service/DataQualityService.md`; der `PRIMÄR`-Beleg belegt nur die Existenz des Verzeichnisses, nicht den Stundenzyklus | **Nachschlagbedarf**: Implementierung des `DataQualityService` lesen |
| SwRS-01 Schichtenarchitektur | die Vorgabe ist dokumentiert, die Einhaltung ist nicht überprüft — die Doku räumt Abweichungen selbst ein | **Nachschlagbedarf**: Abhängigkeitsanalyse der Assemblies |
| SwRS-02 Duale Datenzugriffsimplementierung | die Pflicht ist dokumentiert, die tatsächliche Abdeckung nicht gezählt | **Nachschlagbedarf**: Abgleich `I*Logic` ↔ `BL*Logic`/`WS*Logic` |
| SwRS-23 / SyRS-39 Migration | Mechanismus und Umfang sind primär belegt, die Idempotenzregel jedoch nur über die Dokumentation und ein Beispielskript | **Nachschlagbedarf**: Stichprobe von 20 Skripten auf `IF NOT EXISTS`-Muster |
| SwRS-33 Testarchitektur | Projektstruktur primär belegt, Testabdeckung nicht gemessen | **Nachschlagbedarf**: Abdeckungslauf |
| StRS-Ebene allgemein | Geschäftsziele sind im Code nicht notiert; die `PRIMÄR`-Belege belegen die Fähigkeit, nicht das Ziel | methodisch unvermeidbar — im Vorwort der StRS offengelegt; Validierung durch Fachexperten erforderlich |
Ein weiterer Schwachpunkt: **Es gibt keine quantifizierten Performanceanforderungen.** Die Analyse fand keine
Schwellenwerte für Antwortzeiten, Nutzerzahlen oder Datenvolumen (siehe H-13). Für eine SaaS-Zielarchitektur
ist das eine wesentliche Lücke, die nicht durch Codeanalyse schließbar ist.
### 5.3 Qualität der Fakt-/Aussage-Trennung
Die geforderte Trennung wurde durchgängig eingehalten: `Fakt` enthält ausschließlich zitier- oder
nachprüfbare Beobachtungen (Codezeilen, Aufzählungswerte, Konfigurationseinträge, Fehlermeldungstexte),
`Aussage` die daraus abgeleitete Soll-Formulierung. In vier Fällen war die Interpretation besonders
weitreichend und ist entsprechend vorsichtig formuliert:
- **SyRS-44** (Passwortspeicherung): Der Fakt ist eindeutig (SHA-1, `// TODO the password should be salted!!!`).
Die Aussage formuliert bewusst keine Soll-Aussage über das Bestandssystem, sondern eine Anforderung an das
Zielsystem — eine Soll-Aussage "das System soll SHA-1 verwenden" wäre sachlich falsch gewesen.
- **SyRS-06** (Ticketverlängerung): Ein Performanceverhalten wurde als Anforderung formuliert, obwohl es eine
Implementierungsoptimierung ist. Begründung: Der Kommentar dokumentiert die akzeptierte Nebenwirkung als
bewusste Entwurfsentscheidung, die im Zielsystem bekannt sein muss.
- **StRS-Ebene**: Sämtliche Geschäftsziele sind Interpretation. Dies ist im Vorwort der StRS explizit
offengelegt.
- **SwRS-01/SwRS-02**: Architekturvorgaben aus der Dokumentation wurden als Anforderungen formuliert,
obwohl der Hersteller ihre Nichteinhaltung selbst einräumt. Der Status trägt entsprechend `Workaround`.
### 5.4 Erkenntnisse mit Nachschlagbedarf für eine Folge-Iteration
Nach Priorität geordnet:
**Priorität 1 — abrechnungs- und sicherheitskritisch**
1. **Vertragsabrechnung vollständig durchdringen.** `AutomaticFacturaBL.Contracts.cs` (2.432 Zeilen) wurde
nur im Intervall- und Kontingentabschnitt gelesen. Die Preis-, Rabatt- und Rundungslogik sowie die
Behandlung von Vertragsänderungen mitten in der Periode sind unbelegt. Fehlinterpretationen hier wirken
sich unmittelbar auf Rechnungsbeträge aus.
2. **`ReceiptBL.SaveReceipt` vollständig auswerten.** Die Methode (ab Z. 3517) ist der zentrale
Validierungs- und Speicherpfad aller Belegarten; in diesem Lauf wurden nur die konfigurierbaren
Pflichtfeldprüfungen erfasst. Preisermittlung, Steuerermittlung, Frachtverteilung
(`RecalculateItemsFreightAndDistribution`) und Bestandsbuchung fehlen.
3. **Tokenmodell der Web-Belege** (H-02): anmeldefreier Schreibzugriff ohne belegte Ablaufregel.
4. **Vollständigkeit des DSGVO-Löschumfangs** (H-08) und die wirkungslose Bereinigungsfunktion (H-06).
5. **Provisionsberechnung**: Das Datenmodell ist erfasst, die Berechnungsformel
(`ReceiptProvisionSchemaItem`, `ReceiptProvisionEmployeeLevel`) nicht.
**Priorität 2 — Migrationsentscheidungen**
6. **Delphi-Abgrenzung klären** (H-11). Ohne diese Klärung ist der funktionale Zielumfang unbestimmt.
Konkret zu beantworten: Welche Funktionen sind ausschließlich in Delphi vorhanden?
7. **Produktives Datenbankschema erheben.** Constraints, Indizes, Trigger und tatsächliche Datentypen sind
aus den Mappings nur teilweise ableitbar; für die Datenmigration ist ein Schemaexport erforderlich.
8. **Legacy-REST-Oberfläche klassifizieren.** Die 1.279 POST-Methoden sind nach aktiv genutzt / veraltet /
dubliziert zu ordnen, damit der API-Zielumfang bestimmbar wird.
9. **Nicht genutzte Rechte und Module identifizieren** (H-10) — reduziert den Migrationsumfang messbar.
10. **Semantik von `State` klären** (H-04) — betrifft jede betroffene Tabelle in der Datenmigration.
**Priorität 3 — Vervollständigung der fachlichen Abdeckung**
11. Die 14 in `Hypothesen.md` Abschnitt C genannten Bereiche mit je einem gezielten Analyseschritt erfassen;
besonders Warenwirtschaft (Bestandsbuchungslogik), Reportengine und EDI, da diese in die belegte
Kernlogik hineinwirken.
12. **Mengengerüst und Leistungsziele erheben** (H-13) — nicht aus dem Code, sondern durch Befragung und
Produktivmessung.
13. **Aufbewahrungs- und Archivierungsregeln klären** (H-14) — Abgrenzung GoBD gegen DSGVO-Löschung.
### 5.5 Methodische Beobachtungen zum Lauf (V1 Baseline)
- **Die Entwicklerdokumentation unter `docs/` war der wirksamste Einstiegspunkt.** Besonders
`ai-codebase-navigation.md`, `general-structure.md` und `database-conventions.md` haben die
Suchstrategie erheblich verkürzt. In einer Codebasis dieser Größe ist die Qualität der
Navigationsdokumentation ein bestimmender Faktor für die erreichbare Analysetiefe.
- **Fehlermeldungstexte in der Landessprache sind die ergiebigste Quelle für Geschäftsregeln.** Ein
`Result.AsError("Aufgrund der Mahnstufe darf kein neuer Beleg …")` liefert Regel, Auslöser und
Anwendersicht in einem Beleg. Eine gezielte Suche nach `AsError` in der Geschäftslogik war die
produktivste einzelne Analysetechnik dieses Laufs.
- **Aufzählungstypen mit `[Description]`-Attributen** (`ReceiptState`, `BillingIntervalKinds`,
`ContingentKinds`, `ReceiptCartState`) sind faktisch eine im Code mitgeführte Fachterminologie und
lieferten sowohl Glossareinträge als auch Zustandsräume.
- **Grenze des Prompt-only-Laufs:** Ohne Werkzeugunterstützung zur systematischen Abdeckungsmessung ließ
sich nicht bestimmen, welcher Anteil der Geschäftsregeln erfasst wurde. Die Aussage „X % abgedeckt“ wäre
in dieser Konfiguration nicht belegbar; deshalb ist sie in diesem Bericht bewusst unterlassen. Für
Folge-Iterationen wäre eine werkzeuggestützte Vollzählung der `AsError`-Stellen, der Rechteprüfungen und
der Zustandsübergänge ein geeignetes Abdeckungsmaß.
@@ -0,0 +1,107 @@
# Glossar
**System:** NEXOWARE c-entron ERP-Suite
**Erstellt:** 2026-08-25
Enthält alle Domänen- und Systembegriffe, die in StRS, SyRS und SwRS verwendet werden. Technische Bezeichner
(Klassen, Methoden, Spalten, Tabellen) sind in ihrer Originalschreibweise belassen. Die Spalte *Beleg* nennt
die Fundstelle, aus der die Definition abgeleitet ist.
---
## A. Fachliche Domänenbegriffe
| Begriff | Definition | Beleg |
|---|---|---|
| **Abholschein** | Belegart für die Warenabholung durch den Kunden. Objektart `PickupListClass = 5`. | `Centron.Interfaces/CentronObjectKindNumeric.cs` |
| **Angebot** | Belegart am Anfang der Verkaufsbelegkette. Objektart `OfferClass = 1`, Tabelle `AngKopf`. | `CentronObjectKindNumeric.cs`; `Centron.DAO/Mappings/Sales/CustomerAssets/Offers/OfferMaps.cs` |
| **Anzahlungsrechnung** | Rechnung, die einem Auftrag als Vorauszahlung zugeordnet ist. Beziehung über `RechKopf.DownPaymentForOrderI3D`. | `ReceiptProgressionBL.CreateDownPaymentSql` |
| **Auftrag** | Belegart nach der Angebotsannahme. Objektart `OrderClass = 2`, Tabelle `AufKopf`. | `CentronObjectKindNumeric.cs`; `OrderMaps.cs` |
| **Beleg** (engl. *Receipt*) | Oberbegriff für alle Geschäftsdokumente der Verkaufs- und Einkaufskette. Gemeinsame Basisklasse `ReceiptBase` mit Nummer, Datum, Version, Zustand, Filiale, Währung und Empfängerangaben. | `Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs` |
| **Belegkonditionen** | Stammdaten zu Zahlungs- und Lieferbedingungen eines Belegs. Eigenes Modul `ReceiptConditionManagementAppModuleController`. | `ModuleRegistration.cs`, Region "Stammdaten" |
| **Belegprogression** | Die Menge der Vorgänger- und Nachfolgeobjekte eines Belegs, ermittelt über `ReceiptProgressionBL`. Kennzeichen `IsOrigin` unterscheidet Ursprung von Folgeobjekt. | `Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs` |
| **Belegstatus** (*ReceiptUserState*) | Frei konfigurierbarer, kundenspezifischer Bearbeitungsstatus eines Belegs, unabhängig vom technischen Belegzustand (`ReceiptState`). Optional Pflichtfeld. | `ReceiptBL.UpdateReceiptUserState`; `ApplicationSettingID.ReceiptUserStateRequiredInInvoices` |
| **Belegzustand** (*ReceiptState*) | Technischer Lebenszyklus eines Belegs mit genau drei Werten: `Active` (offen), `Completed` (abgeschlossen), `Canceled` (storniert). | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| **Eskalationsstufe** | Zähler am Ticket, der bei Terminüberschreitung durch `EscalationBL` erhöht und bei Änderung des Fälligkeitsdatums auf 0 zurückgesetzt wird. | `HelpdeskBL.SetHelpdeskAction`; `Centron.BL/Sales/Support/Escalation/EscalationBL.cs` |
| **Filiale** (*Branch*) | Standort innerhalb eines Mandanten. Trägt eigene Nummernkreise und begrenzt über restriktive Rechte den Datenzugriff. | `Centron.Entities/Entities/BranchArea/Branch.cs` |
| **Firmengruppe** | Zusammenfassung mehrerer Kunden, deren Angaben (z. B. Leitweg-ID, ZUGFeRD-Kennzeichen) Vorrang vor den Angaben des Einzelkunden haben. | `ReceiptBL.GetCompanyGroupCustomerI3DForReceiptData` |
| **Gutschrift** | Belegart zur Rückvergütung. Objektart `CreditVoucherClass = 6`. | `CentronObjectKindNumeric.cs` |
| **Helpdesk / Ticket** | Serviceanfrage mit Kunde, Ansprechpartner, Kategorie, Priorität, Status, Fälligkeit, verantwortlicher Person und Bearbeiterkreis. Objektart `HelpdeskClass = 10`. | `Centron.BL/Sales/Support/HelpdeskBL.cs`; `CentronObjectKindNumeric.cs` |
| **Kalkulation** | Einkaufsseitige Preisermittlung beim Wareneingang; Modul "Eingang/Kalk" (`SupplierReceiptDocumentsImportAppModuleController`, Recht `RIGHT_KALKULATIONERSTELLEN`). | `ModuleRegistration.cs`, Region "Einkauf" |
| **Kommissionierung** | Zusammenstellen der Ware zu einem Auftrag; Modul `OrderCommissionAppModuleController`, Rückmeldung über `UpdateReceiptQuantityPicked`. | `ModuleRegistration.cs`; `ReceiptBL.UpdateReceiptQuantityPicked` |
| **Kontingent** | Im Vertrag vereinbartes Leistungsvolumen, bemessen in Stunden (`ContingentKinds.Hour`) oder Geldwert (`ContingentKinds.Money`), begrenzt prozentual oder absolut (`ContingentLimitKinds`). | `Centron.Interfaces/Sales/BillingCenter/Contracts/ContingentKinds.cs`, `ContingentLimitKinds.cs` |
| **Kostenstelle / Kostenträger** | Stammdaten der internen Kostenrechnung; Modul `PayersAndCostCenterAppModuleController`, BL `CostCenterBL` / `CostObjectBL`. | `ModuleRegistration.cs`; `Centron.BL/Warehousing/CostCenterBL.cs` |
| **Leitweg-ID** | Bundesweit eindeutige Adressierungskennung öffentlicher Auftraggeber für die elektronische Rechnung. Feld `AccountCustomer.LeitwegID`. | `ReceiptBL.GetLeitwegID` |
| **Lieferschein** | Belegart der Warenauslieferung. Objektart `DeliveryListClass = 3`, Tabelle `LiefKopf`. | `CentronObjectKindNumeric.cs`; `DeliveryListMaps.cs` |
| **Mahnstufe** (*DunningLevel*) | Stand des Mahnverfahrens je Kunde, Wertebereich 0–3 (0 = keine Mahnstufe erreicht). Ab einer konfigurierten Schwelle sperrt sie die Belegneuanlage. | `ReceiptBL.GetCustomerOrSupplierDunningLevel` |
| **Mandant** | Rechtliche Einheit; oberste Ordnungsebene über den Filialen. Objektart `Company = 53` ("Mandant"). | `CentronObjectKindNumeric.cs`; `Branch.MandatorI3D` |
| **MSP** (*Managed Service Provider*) | Geschäftsmodell der laufenden IT-Betreuung; im System als eigener Auswertungs- und Verrechnungsbereich (MSP-Collector, MSP-Auswertung, MSP-Dashboard) abgebildet. | `ModuleRegistration.cs`, Region "Controlling/Analytics"; `Centron.BL/Statistics/MspCollectors/` |
| **Nummernkreis** (*NumberGroup*) | Konfiguration der automatischen Nummernvergabe je Objektart, Filiale und Mandant mit Bereich (`RangeFrom`/`RangeTo`), Schrittweite (`Interval`) und aktuellem Stand (`Current`). | `Centron.BL/Administration/Company/NumberGroupBL.cs` |
| **OPOS** | Offene-Posten-Verwaltung; Übersicht unbezahlter Belege. Modul `OposOverviewAppModuleController`. | `ModuleRegistration.cs`; `Centron.BL/Sales/Receipts/Invoices/Opos/` |
| **Pauschalabrechnung** | Abrechnung eines Projekts zum Festpreis unabhängig vom Aufwand. Modul `FlatRateProjectAppModuleController`. | `ModuleRegistration.cs`, Region "Abrechnung" |
| **Provisionsschema** | Regelwerk zur Ermittlung der Vertriebsprovision aus Verkaufsbelegen, kundenbezogen zuordenbar. | `Centron.Entities/…/Receipts/ReceiptProvisionSchema.cs`, `…SchemaCustomerAssignment.cs` |
| **Rechnung** | Belegart der Forderungsstellung. Objektart `InvoiceClass = 4`, Tabelle `RechKopf`. | `CentronObjectKindNumeric.cs`; `InvoiceMaps.cs` |
| **RMA** (*Return Merchandise Authorization*) | Rücksende- und Reparaturvorgang mit drei eigenen Nummernkreisen (`RepairEntrance`, `RMANumber`, `Reshipment`). | `Centron.BL/CustomerArea/RmaBL.cs` |
| **Sonderpreis** | Kundenindividueller Artikelpreis; Grundlage des im Kundenportal angebotenen Artikelsortiments. | README.md, Abschnitt "Contributing / 1. WebCart"; `AccountSpecialPriceConfiguration.cs` |
| **Stammblatt** (*MasterDataList*) | Zusammenfassende Datenblattdarstellung zu einem Kunden oder Gerät. Objektart `MasterDataListClass = 25`. | `CentronObjectKindNumeric.cs`; `MasterDataListOverviewAppModuleController` |
| **Vereinfachte Ticketabrechnung** (*TimerBilling*) | Abrechnungsverfahren, das erfasste Ticketzeiten direkt in einen Verkaufsbeleg überführt. | `ReceiptBL.CreateNewReceiptForHelpdekTimers`; `Centron.BL/Sales/CustomerAssets/TimerBilling/TimerBillingBL.cs` |
| **Vertrag** | Wiederkehrende Leistungsvereinbarung mit Abrechnungsintervall, Abrechnungsrichtung, Kontingent und Berechnungsart. Objektart `ContractClass = 22`. | `CentronObjectKindNumeric.cs`; `Centron.Interfaces/Sales/BillingCenter/Contracts/` |
| **Vertragsabrechnung** (*AutomaticFactura*) | Automatisierte Fakturierung fälliger Verträge. Modul `AutomatedBillingAppModuleController`. | `Centron.BL/Sales/CustomerAssets/AutomaticFactura/` |
| **vorschüssig / nachschüssig** | Abrechnungsrichtung eines Vertrags: `Billingadvance` fakturiert vor, `Billingarrear` nach dem Leistungszeitraum. | `Centron.Interfaces/Sales/BillingCenter/Contracts/BillingKind.cs` |
| **Warengruppe** | Klassifikationsstufe des Artikelstamms. Objektarten `MaterialGroup = 70`, `SecondaryMaterialGroup = 136`. | `CentronObjectKindNumeric.cs`; `MaterialGroupAppModuleController` |
| **Warenkorb** (*WebCart / ReceiptCart*) | Vom Kunden im Portal zusammengestellte Bedarfsliste, technisch ein Angebot (`ReceiptOffer`) mit eigenem Freigabezustand `CartState`. | `Centron.Interfaces/Sales/Receipts/ReceiptCartState.cs`; `ReceiptCartReleaseSystemBL` |
| **Web-Account** | Kundenzugang zum Portal. Eigenes Konto- und Rechtemodell, getrennt vom Mitarbeiterkonto. Objektart `Webaccount = 131`. | `Centron.BL/Administration/Logins/WebAccountBL.cs`; `WebAccountRightsConst.cs` |
| **Web-Beleg** (*WebReceipt*) | Über einen Weblink für den Kunden bereitgestellter Beleg mit eigenem Freigabe- und Signaturzustand. | `Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs` |
| **XRechnung / ZUGFeRD** | Deutsche bzw. deutsch-französische Norm für die elektronische Rechnung. ZUGFeRD ist hybrid (PDF/A mit eingebettetem XML), XRechnung rein strukturiert. | `docs/guides/development/xrechnung.md`; `Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs` |
| **Zeiterfassung** (*HelpdeskTimer*) | Ticketbezogene Arbeitszeiterfassung mit Abrechenbarkeitskennzeichen, Leistungsartikel und optionaler Belegzuordnung. Objektart `HelpdeskTimerClass = 4000056`. | `Centron.Entities/…/HelpdeskTimerArea/HelpdeskTimer.cs` |
---
## B. System- und Architekturbegriffe
| Begriff | Definition | Beleg |
|---|---|---|
| **ApplicationKind** | Katalogeintrag einer am Web-Service anmeldeberechtigten Client-Anwendung mit Lizenz-GUID, Sitzungsdauer, Lizenzzählmodell sowie erforderndem und ausschließendem Recht. | `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| **ApplicationSettingID** | Aufzählung der Kennungen aktueller Anwendungseinstellungen (Tabelle `ApplicationSettings`). | `Centron.Interfaces/Administration/Settings/ApplicationSettingID.cs` |
| **AppSettingsConst** | Aufzählung der Kennungen historischer Anwendungseinstellungen (Tabelle `Stammdat`); für Neuentwicklung nicht mehr zu verwenden. | `docs/guides/development/settings-management.md` |
| **AppUser** | Mitarbeiterbenutzerkonto, Tabelle `Sichbenu`. Trägt Anmeldeverfahren (`AuthentificationKind`), Sperrkennzeichen und Passworthash. | `Centron.DAO/Mappings/Administration/AppUserMaps.cs` |
| **BLSession / DAOSession** | Sitzungsobjekt der Geschäftslogik bzw. des Datenzugriffs; kapselt die NHibernate-Sitzung und die Transaktionssteuerung (`WithTransaction`, `StartTransaction`, `RollbackTransaction`). | `Centron.BL/BLSession.cs`; Verwendung in allen `*BL`-Klassen |
| **CentronObjectKindNumeric** | Systemweiter numerischer Objekttypschlüssel. Neue Werte dürfen ausschließlich am Ende ergänzt werden. | `Centron.Interfaces/CentronObjectKindNumeric.cs` |
| **ClassContainer** | Singleton-Container des WPF-Clients, der `I*Logic`-Schnittstellen namensbasiert auf `BL*Logic` oder `WS*Logic` auflöst. | `docs/getting-started/general-structure.md`; `Centron.WPF.UI/Services/Container/` |
| **ConcurrencyControlGuid** | Kennung am Beleg zur optimistischen Nebenläufigkeitskontrolle; Abweichung führt zu `DefaultMessageCodes.ChangedByOtherInstance`. | `ReceiptBase.cs`; `ReceiptBL.cs` |
| **DefaultMessageCodes** | Katalog maschinenlesbarer Fehlerursachen (u. a. `RightCheckFailed`, `ChangedByOtherInstance`, `LicenseMaximumReached`, `TwoFactorAuthFailed`, `BadRequest`). | Verwendung in `Centron.BL/**` |
| **DTO** (*Data Transfer Object*) | Transportobjekt zwischen Web-Service und Client; darf keine NHibernate-Bindung tragen. | `docs/reference/architecture/dtos-and-entities.md` |
| **Entity** | Persistente Objektabbildung einer Datenbanktabelle; verlässt die Geschäftslogikschicht nicht. | `docs/reference/architecture/dtos-and-entities.md` |
| **I3D** | Primärschlüsselspalte aller Tabellen, Abkürzung für "ID 3develop". Auch Kennung eines Rechts. | `docs/guides/database/database-conventions.md`; `docs/guides/development/add-a-new-right.md` |
| **ILogic / BLLogic / WSLogic** | Schnittstelle des Client-Datenzugriffs und ihre beiden Pflichtimplementierungen (direkter Datenbankzugriff bzw. Web-Service-Aufruf). | `docs/getting-started/general-structure.md` |
| **LicenseGuids** | Katalog aller Lizenz-GUIDs; jede Lizenz kann Anzahl, Gültigkeitsdatum und Höchstversion tragen. | `docs/reference/security/licensing-system.md` |
| **LicenseUsageKind** | Zählmodell einer Lizenz: `PerUser` (je Benutzer) oder `PerUserAndPerMachine` (je Benutzer und Gerät). | `ApplicationKind.cs` |
| **LoggedInUser** | Angemeldete Identität; kapselt entweder einen `AppUser` oder einen `WebAccount`. Unterscheidungsmerkmal `IsWebAccountLogin`. | `Centron.BL/Administration/Logins/Auth/Authenticator.cs` |
| **NamedQuery** | Vorkonfigurierte, parametrisierte SQL-Abfrage, adressiert über `NamedQueryEnums`. | `Centron.DAO/NamedQueries/`; Verwendung in `AutomaticFacturaBL`, `HelpdeskCloseBL` |
| **Nexus** (*c-entron Nexus*, früher *c-entron Web*) | Blazor-Server-Portal mit zwei Bereichen: ServiceBoard für Mitarbeiter und Kundenportal/WebCart für Kunden. | README.md; `src/nexus/CentronNexus/` |
| **ObjectMapper** | Zentrale Abbildungskomponente zwischen Entitäten und DTOs, konfiguriert über 85 Profile. | `Centron.BL/WebServices/ObjectMapperConfiguration/` |
| **restriktives Recht** (*restricting right*) | Recht, das den Datenumfang eines bereits berechtigten Benutzers einschränkt (z. B. "nur eigene", "nur eigene Filiale") statt Zugriff zu gewähren. | `CentronRights.md` |
| **Result / Result\<T\>** | Einheitliches Ergebnisobjekt der Geschäftslogik mit `Status` (`Success`/`Error`/`Warning`), `Message`, `MessageCode` und optional `Data`. | `docs/reference/architecture/results-and-responses.md` |
| **ScriptMethod** | Nummerierte Migrationsklasse zur Fortschreibung des Datenbankschemas beim Anwendungsupdate. | `docs/guides/database/create-scripts.md`; `Centron.BL/Administration/Scripts/ScriptMethods/Scripts/` |
| **ServiceBoard** | Mitarbeiterbereich des Nexus-Portals (Ticketliste, Kanban, Zeiterfassung, Statistiken). | `src/nexus/CentronNexus/ServiceBoard/` |
| **Sichbenu** | Datenbanktabelle der Mitarbeiterbenutzerkonten. | `Centron.DAO/Mappings/Administration/AppUserMaps.cs` |
| **Sichrech** | Datenbanktabelle des Rechtekatalogs (Spalten `I3D`, `Text`, `OwnerRecht`, `NumChildren`, `Beschreibung`). | `Centron.DAO/Mappings/Administration/AppRightMaps.cs`; `docs/guides/development/add-a-new-right.md` |
| **Stammdat** | Historische Datenbanktabelle der Anwendungseinstellungen. | `docs/guides/development/settings-management.md` |
| **Ticket** (Sitzung) | Sitzungsschlüssel des Web-Service mit Ablaufdatum, Anwendungsbezug, Lizenz und Gerätekennung. **Nicht** zu verwechseln mit dem Serviceticket (Helpdesk). | `Centron.BL/Administration/Logins/TicketBL.cs` |
| **UserRightsConst** | Zentraler Katalog der Mitarbeiterrechte-IDs als geschachtelte Konstantenklassen. | `…/Administration/Rights/UserRightsConst.cs` |
| **WebAccountRightsConst** | Getrennter Katalog der Kundenrechte als Aufzählung. | `…/Administration/Rights/WebAccountRightsConst.cs` |
| **WebServiceBL** | Schicht, die zwischen Entitäten und DTOs abbildet und die Geschäftslogik für den Web-Service kapselt. | `docs/guides/services/add-webservice-methods.md` |
---
## C. Begriffsabgrenzungen (Verwechslungsgefahr)
| Begriffspaar | Abgrenzung |
|---|---|
| **Ticket** (Sitzung) vs. **Ticket** (Serviceanfrage) | `TicketBL` verwaltet Anmeldesitzungen; `HelpdeskBL` verwaltet Serviceanfragen. Beide werden im Code "Ticket" genannt. In dieser Spezifikation wird die Sitzung stets als "Sitzung (Ticket)" und die Serviceanfrage als "Ticket" bzw. "Helpdesk" bezeichnet. |
| **Belegzustand** (`ReceiptState`) vs. **Belegstatus** (`ReceiptUserState`) | `ReceiptState` ist der feste technische Lebenszyklus (offen/abgeschlossen/storniert); `ReceiptUserState` ist ein frei konfigurierbarer, kundenspezifischer Bearbeitungsstatus. |
| **Recht** (`UserRightsConst`) vs. **Lizenz** (`LicenseGuids`) | Ein Recht steuert, *wer* darf; eine Lizenz steuert, *ob das Produkt* darf. Modulsichtbarkeit erfordert beides (SyRS-09). |
| **Mandant** vs. **Filiale** | Der Mandant ist die rechtliche Einheit, die Filiale der Standort darunter. Nummernkreise können auf beiden Ebenen definiert sein. |
| **Kunde** (`Customer`) vs. **Account** | Das System befindet sich in einer Umstellung auf ein einheitliches `Account`-Modell (Einstellung `IsAccountManagementActive`); je nach Schalter wird das Modul `AccountManagementAppModuleController` oder `CrmAppModuleController` registriert. Beide Modelle existieren parallel. |
| **State** (`DBEntity.State`) vs. **IsDeleted** | Beide kodieren Aktiv-/Inaktivzustände; `State` ist ein nullable int mit implizit `1` = aktiv, `IsDeleted` ein bit nach der Datenbankkonvention. Siehe Hypothese H-04. |
| **c-entron.NET** vs. **c-entron (Delphi)** | Die untersuchte Codebasis ist der .NET-Anteil. Es existiert nachweislich eine parallele Delphi-Anwendung, die Teile der Fachlichkeit abdeckt und **nicht** Teil des Untersuchungsgegenstands ist. Siehe Hypothese H-11. |
@@ -0,0 +1,196 @@
# Hypothesen und offene Fragen
**System:** NEXOWARE c-entron ERP-Suite
**Erstellt:** 2026-08-25
**Zweck:** Sammlung aller Aussagen, die sich aus den vorliegenden Artefakten **nicht eindeutig** belegen ließen,
jeweils mit der Angabe, welche Information zur Bestätigung fehlt. Dieses Dokument ist die Arbeitsgrundlage für
Schritt 7 der RRE-Methodenkette (Validierung durch Fachexperten).
---
## Abschnitt A — Als `[HYPOTHESE]` markierte Anforderungen der Spezifikation
Diese Aussagen sind Bestandteil des Anforderungs-Sets, tragen dort aber den Status `HYPOTHESE`.
### H-01 — SwRS-34: Entwicklerschutz gegen versehentlichen Außenkontakt
| Feld | Inhalt |
|---|---|
| **Anforderung** | SwRS-34 |
| **Aussage** | In DEBUG-Builds werden alle externen E-Mail-Adressen durch `test@nexoware.com` ersetzt; als intern gilt eine Adresse, die auf `nexoware.com` endet. Abschaltbar über `AllowSendingEmailToExternalAddresses`. |
| **Vorliegende Belege** | Ausschließlich `docs/reference/security/developer-security.md` (Klassifikation `KONTEXT`). |
| **Warum Hypothese** | Die Datei `DeveloperSecurity.cs` wurde in diesem Lauf nicht eingesehen. Der Beleg ist Entwicklerdokumentation, kein durchgesetzter Code. |
| **Fehlende Information** | Einsicht in `DeveloperSecurity.cs`: tatsächliche Adressersetzungslogik, Abgrenzung über `#if DEBUG`, Wirkungsbereich (nur SMTP oder auch Microsoft-Graph-Versand), Verhalten bei CC/BCC. |
| **Risiko bei Fehlannahme** | Gering für die Zielarchitektur (reines Entwicklungswerkzeug), aber relevant für die Testkonzeption der Migration. |
| **Prüffrage an den Fachexperten** | Greift der Schutz auch beim Versand über Microsoft Graph und beim Massenmailing (Kampagnen)? |
---
## Abschnitt B — Offene Fragen zu belegten Anforderungen
Diese Punkte betreffen Anforderungen mit Status `belegt` bzw. `belegt; Workaround`, bei denen ein
Teilaspekt unbeantwortet blieb. Sie sind **nicht** als eigene Anforderungen geführt.
### H-02 — Gültigkeitsdauer der Web-Beleg-Token (zu SyRS-46)
**Beobachtung:** `ReceiptBL.ChangeWebReceiptPurchaseOrderNumber(string token, string newPurchaseOrderNumber)`
und `ChangeWebReceiptAddress(string token, …)` erlauben anmeldefreie Schreibzugriffe auf einen Beleg, allein
über ein Token.
**Nicht belegt:** Gültigkeitsdauer, Einmaligkeit, Widerrufbarkeit und Entropie des Tokens sowie die Frage, ob
das Token nach Belegabschluss ungültig wird.
**Fehlende Information:** Implementierung der Tokenerzeugung und -prüfung (`GenerateTokenForDocumentRequest`,
`SharedDocument`), zugehöriges Datenbankschema.
**Warum relevant:** Sicherheitsrelevante Anforderung an ein SaaS-Zielsystem; ohne Ablaufregel entstünde ein
dauerhaft gültiger, nicht widerrufbarer Schreibzugriff.
### H-03 — Sperrschwelle je Belegart im Mahnwesen (zu SyRS-22)
**Beobachtung:** `BlockNewReceiptsDunningLevel(customerOrSupplierI3D)` liefert die Sperrschwelle je Belegart.
**Nicht belegt:** Wo dieser Wert konfiguriert wird (Anwendungseinstellung, Belegkonditionen oder Kundenstamm)
und welche Standardwerte je Belegart gelten.
**Fehlende Information:** Implementierung von `BlockNewReceiptsDunningLevel` in den
`IReceiptSpecificLogic`-Ableitungen der einzelnen Belegarten.
**Warum relevant:** Bestimmt, ob die Kreditsperre eine globale, eine kundenbezogene oder eine
belegartbezogene Einstellung ist — das verändert das Konfigurationsmodell des Zielsystems.
### H-04 — Semantik von `DBEntity.State` (zu SwRS-07)
**Beobachtung:** Zahlreiche Abfragen filtern auf `f.State == 1` (u. a. `CTRTypesBL`,
`HelpdeskCategoryPatternBL`, `HelpdeskPrioritiesBL`, `HelpdeskDeviceLinkBL`), `EscalationBL` behandelt
`f.State == 0` als deaktiviert.
**Nicht belegt:** Ob `State` systemweit dieselbe Bedeutung trägt (`0` = inaktiv, `1` = aktiv) oder je
Entität abweichend belegt ist; ob weitere Werte vorkommen.
**Fehlende Information:** Vollständige Auswertung aller `State`-Zuweisungen und -Vergleiche sowie der
zugehörigen Datenbestände.
**Warum relevant:** Betrifft die Datenmigration jeder betroffenen Tabelle.
### H-05 — Einheit des Feldes `HelpdeskTimer.Timer` (zu SwRS-20)
**Beobachtung:** `HelpdeskTimer` führt `public virtual int Timer { get; set; }` ohne Einheitenangabe;
`LunchTime` trägt den Kommentar "lunchtime is in seconds!".
**Nicht belegt:** Ob `Timer` in Sekunden oder Minuten geführt wird und ob `Timer` gegenüber
`Stop - Start` redundant ist.
**Fehlende Information:** Auswertung der Berechnungsstellen in `HelpdeskTimerBL` /
`HelpdeskTimeRecordingBL` sowie der Reportvorlagen.
**Warum relevant:** Direkter Einfluss auf abgerechnete Beträge; eine Fehlinterpretation um den Faktor 60 wäre
fakturierungsrelevant.
### H-06 — Wirkungslosigkeit von `DataSecurityExecuteCleanUp` (zu SyRS-45)
**Beobachtung:** `DataSecurityBL.DataSecurityExecuteCleanUp(AppUser, IList<DataSecurityCleanUpStatsKind>,
DataSecurityCleanUpStatsFilter)` prüft die Rechte und gibt dann unmittelbar `Result.AsSuccess()` zurück,
ohne eine Bereinigung auszuführen. Mehrere Löschpfade (`DoDeleteCustomer`, `DoDeleteSupplier`,
`DoDeleteAccount`) sind auskommentiert.
**Nicht belegt:** Ob die Funktion bewusst deaktiviert wurde (z. B. wegen Datenverlustrisiko) oder ob es sich
um einen unfertigen Stand handelt.
**Fehlende Information:** Änderungshistorie der Datei, zugehörige Tickets, Aussage der Entwicklung.
**Warum relevant:** Das DSGVO-Modul verspricht anwenderseitig eine Bereinigungsfunktion, die derzeit nichts
tut — für die Migration muss der Sollzustand geklärt werden.
### H-07 — Fehlende RMA-Prüfung beim Ticketabschluss (zu SyRS-28, StRS-26)
**Beobachtung:** `HelpdeskCloseBL.CanCloseHelpdesk(int helpdeskI3D)` enthält den Kommentar
`//Todo: if rma exists check if finished` und gibt unbedingt `true` zurück.
**Nicht belegt:** Ob die Kopplung "Ticket erst schließbar, wenn zugehörige RMA abgeschlossen" fachlich
gewünscht ist oder ob die Anforderung fallengelassen wurde.
**Fehlende Information:** Ticketreferenz zur ursprünglichen Anforderung; Aussage der Fachabteilung.
**Warum relevant:** Entscheidet, ob im Zielsystem eine zusätzliche Abschlussbedingung zu implementieren ist.
### H-08 — Vollständigkeit des DSGVO-Löschumfangs (zu SyRS-45)
**Beobachtung:** Gelöscht werden Ansprechpartner, Kontaktmanagement-Kontakte und Account-Adresskontakte;
Kunden, Lieferanten und Accounts sind im Code als Löschpfade auskommentiert.
**Nicht belegt:** Ob personenbezogene Daten außerhalb der Kontakttabellen (z. B. Empfängerangaben in
`ReceiptReceiver`, Freitextfelder in Tickets, Mailanhänge, Protokolltabellen) mit erfasst werden.
**Fehlende Information:** Vollständige Datenflussanalyse personenbezogener Merkmale.
**Warum relevant:** Ein unvollständiges Löschkonzept ist ein datenschutzrechtliches Risiko des Zielsystems.
### H-09 — Vorrangregel zwischen Sperre und Änderungskennung (zu SyRS-18, SyRS-19)
**Beobachtung:** Belege werden sowohl pessimistisch gesperrt (`TryLockReceipt`) als auch optimistisch über
`ConcurrencyControlGuid` geprüft.
**Nicht belegt:** Welcher Mechanismus in welchem Aufrufpfad greift und ob es Pfade gibt, in denen nur einer
von beiden wirkt.
**Fehlende Information:** Vollständige Aufrufanalyse aller schreibenden Belegoperationen.
**Warum relevant:** Für ein Web-Zielsystem ist eine eindeutige Nebenläufigkeitsstrategie festzulegen.
### H-10 — Nicht mehr genutzte Rechte und Module
**Beobachtung:** `UserRightsConst` enthält zahlreiche `[Obsolete]`-Konstanten; `WebAccountRightsConst`
enthält mehr als 15 `[Obsolete]`-Werte (Riversuite, Supremo, Monitoring). `CentronRights.md` hält zu
`UserRightsConst.RIGHT_KALENDERANZEIGENALLE` fest: "Currently, this right is not used."
Die Modulregistrierung enthält eine als "obsolate" bezeichnete Region (Passwort Manager).
**Nicht belegt:** Welche dieser Rechte und Module tatsächlich noch produktiv verwendet werden.
**Fehlende Information:** Auswertung der Rechtezuweisungen in Produktivdatenbanken.
**Warum relevant:** Bestimmt den Migrationsumfang; als nicht genutzt bestätigte Rechte und Module entfallen.
### H-11 — Reichweite der Delphi-Altanwendung
**Beobachtung:** Der Code verweist mehrfach auf eine parallel betriebene Delphi-Anwendung: Kommentare in
`UserRightsConst.cs` ("`FomName` is important for Delphi"), `CentronObjectKindNumeric.cs`
("Neue Konstanten für .NET werden autarg von c-entron Delphi angelegt Sie beginnen ab dem Wert 7600000"),
`ApplicationSettingDefinitions.cs` ("it is not possible to create new customers and suppliers through
c-entron (delhpi)") sowie `LicenseManager.TryFixCentronDelphiVersionNumber`.
**Nicht belegt:** Welche fachlichen Funktionen ausschließlich in der Delphi-Anwendung existieren und daher in
dieser Codebasis **nicht** analysierbar sind.
**Fehlende Information:** Zugriff auf die Delphi-Codebasis oder eine Funktionsliste.
**Warum relevant:** Dies ist die größte bekannte Lücke des Untersuchungsgegenstands: Die Spezifikation kann
per Konstruktion nur den .NET-Anteil abdecken. Ein Zielsystem müsste den Delphi-Anteil mit abdecken.
### H-12 — Verschlüsselungsverfahren vertraulicher Einstellungen (zu SyRS-47)
**Beobachtung:** `ApplicationSettingDefinitions` beschreibt `DownloadLogsFtpPassword` als
"Stored in encrypted format and in Monitoring service we will decrpt and use."
**Nicht belegt:** Verwendetes Verfahren, Schlüsselverwaltung und Schlüsselrotation.
**Fehlende Information:** Implementierung der Ver-/Entschlüsselung von Einstellungswerten.
**Warum relevant:** Für ein SaaS-Zielsystem ist die Geheimnisverwaltung (Secret Management) neu zu
konzipieren; das Bestandsverfahren muss dafür bekannt sein.
### H-13 — Mengengerüst und Leistungsanforderungen
**Beobachtung:** Es existiert eine Testklasse `tests/Centron.Tests.EndToEnd/Infrastructure/PerformanceTest.cs`
sowie Module "Profiling"/`ProfilerSettingsController` und ein Verzeichnis
`Centron.BL/Administration/PerformanceTests`.
**Nicht belegt:** Konkrete Leistungsziele (Antwortzeiten, gleichzeitige Nutzer, Datenvolumen), da keine
Schwellenwerte in Konfiguration oder Code gefunden wurden.
**Fehlende Information:** Service-Level-Vorgaben, Produktivkennzahlen, Inhalte der Leistungstests.
**Warum relevant:** Ohne Mengengerüst lassen sich für die SaaS-Neuimplementierung keine belastbaren
Performance-Anforderungen formulieren. Aus diesem Grund enthält die Spezifikation bewusst **keine**
quantifizierten Performanceanforderungen — die einzige belegte quantitative Aussage ist die interne
5-Minuten-Schwelle der Ticketverlängerung (SyRS-06).
### H-14 — Aufbewahrungsfristen und Archivierung
**Beobachtung:** Es existiert die Einstellung `InvoiceArchiveActive` ("When this setting is active, the
functionality for invoice archive is enabled.") sowie ein Modul "Stammblätter" und ein
Buchhaltungsexport mit Wirtschaftsjahresbeginn.
**Nicht belegt:** Gesetzliche Aufbewahrungsfristen, Archivierungs- und Löschregeln für Belege sind nicht als
durchgesetzte Regel im Code auffindbar.
**Fehlende Information:** Implementierung der Rechnungsarchivfunktion; organisatorische Vorgaben.
**Warum relevant:** Für ein SaaS-Zielsystem sind Aufbewahrung (GoBD) und DSGVO-Löschung gegeneinander
abzugrenzen; beides ist derzeit nur ansatzweise belegt.
---
## Abschnitt C — Bereiche ohne belastbare Analysetiefe
Für die folgenden Bereiche wurden Existenz und grobe Verortung festgestellt, aber keine Anforderungen
formuliert, weil die Analysetiefe dafür nicht ausreichte. Jede Aussage über diese Bereiche wäre eine
Hypothese; sie sind daher bewusst **nicht** im Anforderungs-Set enthalten.
| Bereich | Verortung | Was fehlt |
|---|---|---|
| Produktionsplanung | `Centron.BL/Production/`, `CentronNexus/ProductionOrderManagement/`, Module Maschinenverwaltung & Produktionsaufträge (ohne Rechteprüfung, nur Lizenz `ProductionManagement`) | Statusmodell der Produktionsaufträge, Arbeitsschritte, Kapazitätsplanung |
| Passwort-Manager | `Centron.BL/PasswordManager/`, `PasswordManagementArea/`, Module Zugänge/Richtlinien/Zugangsbereiche (in der Registrierung als "obsolate" markiert) | Verschlüsselung der abgelegten Zugangsdaten, Freigabemodell |
| MSP-Collector / MSP-Auswertung | `Centron.BL/Statistics/MspCollectors/`, `MspEvaluationSettings` | Datenquellen, Kennzahlendefinitionen, Verrechnungslogik (`CreateSpecialArticleToContractFromMspEvaluation`) |
| EDI (Lieferanten, OpenTRANS, ALSO) | `Centron.BL/EDI/`, `Centron.BL/DataExchange/EDI/` | Nachrichtentypen, Fehler- und Wiederholungsverhalten |
| Kalender / Terminplanung / Exchange-Sync | `Centron.BL/Calendar/`, `docs/features/exchange-sync-bugprotokoll.md` | Synchronisationsrichtung, Konfliktauflösung |
| TAPI / Telefonie | `Centron.BL/Tapi/`, `docs/reference/architecture/tapi.md`, Modul Telefonate | Anrufzuordnung, Protokollierung |
| KI-Assistenz | `Centron.BL/ArtificialIntelligence/`, Modul AI-Chat, `AiTextRatingJson` in `HelpdeskTimer` | Verarbeitete Daten, Anbieter, Datenschutzfolgen |
| Mobile / Außendienst | `Centron.Entities/Entities/Mobile/`, `NewMobileHelpdeskState` | Abgleichverfahren, Offlinefähigkeit |
| Dokumentations-Assistent (DocumentationWizard) | 8 Objektarten in `CentronObjectKindNumeric` (5101350–5101430) | Fachlicher Zweck und Prozess |
| Inventur im Detail | `Centron.BL/Warehousing/InventoryManagement/` (`InventoryBL` und `InventoryNewBL` parallel) | Zählverfahren, Differenzbehandlung, Grund der Doppelimplementierung |
| Reportengine | `Centron.BL/ReportEngine/`, `Centron.Entities/Entities/ReportEngine/` | Reportmodell, Variablenersetzung, Berechtigungen auf Reportebene |
| Online-Banking / FinAPI | `Centron.BL/Finances/OnlineBanking/`, `Centron.APIs.FinAPI` (72 Dateien) | Kontoabgleich, Zahlungszuordnung, PSD2-Anforderungen |
| Massenaktualisierung (Data Updater) | `Centron.BL/MassUpdate/`, Modul Data Updater | Umfang der änderbaren Felder, Absicherung gegen Massenfehler |
| Checklisten / C-FLOW-Ticketvorlagen | `Centron.BL/CheckListArea/`, `TicketProcessTemplates` | Vorlagenmodell, Ausführungssemantik |
@@ -0,0 +1,844 @@
# StRS — Stakeholder Requirements Specification
**System:** NEXOWARE c-entron ERP-Suite (c-entron.NET / c-entron Nexus)
**Verfahren:** Reverse Requirements Engineering, statische Artefaktanalyse
**Norm:** ISO/IEC/IEEE 29148:2018, Abschnitt Stakeholder Requirements
**Codebasis:** `C:\DEV\MasterArbeit\QuellCode\CentronERP` (nur lesend analysiert)
**Erstellt:** 2026-08-25
---
## Vorbemerkung zur Belegführung
Alle Pfadangaben sind relativ zum Wurzelverzeichnis der Codebasis. Belege sind klassifiziert als
`PRIMÄR` (durchgesetzte Regel in Code oder DB-Constraint), `SEKUNDÄR` (UI-Label, Fehlermeldung,
Konfigurationsschalter, Mappingtabelle, Reportlayout) oder `KONTEXT` (Kommentar, Entwicklerdokumentation,
Commit-Message, Ticketreferenz).
Auf StRS-Ebene ist die Belegbasis naturgemäß indirekter als auf SyRS-/SwRS-Ebene: Geschäftsziele sind im
Code nicht explizit notiert. Die hier geführten `PRIMÄR`-Belege belegen daher jeweils, **dass die
Fähigkeit im System existiert und erzwungen wird**; die Zuordnung zu einem Geschäftsziel ist die
dokumentierte Interpretation im Feld `Aussage`.
---
## StRS-01
```
ID: StRS-01
Titel: Mandanten- und Filialstruktur als Organisationsrahmen
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung / Systemadministrator
Vorbedingung: Das Unternehmen betreibt mehrere rechtliche Einheiten (Mandanten) und/oder Standorte (Filialen).
Fakt: Die Entität `Branch` (Tabelle über `BaseBranch`) führt ein Pflichtfeld `MandatorI3D`; `ReceiptBase`
führt `BranchI3D` und `BranchOrigin`; Nummernkreise werden über `MandatoryBL.GetNumberGroup(numberGroup, branch)`
filial- und mandantenspezifisch aufgelöst.
Aussage: Das System soll Geschäftsvorfälle einer Filiale und einem Mandanten zuordnen, damit ein
Unternehmensverbund mit mehreren Standorten und rechtlichen Einheiten in einer Installation
abgebildet werden kann.
Ergebnis: Belege, Tickets, Mitarbeiter und Nummernkreise sind einer Filiale zugeordnet; Auswertungen und
Rechteprüfungen können nach Filiale eingeschränkt werden.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/BranchArea/Branch.cs — Eigenschaft `MandatorI3D` (nicht nullable int) — Begründung: Belegt strukturell die Zuordnung jeder Filiale zu genau einem Mandanten.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs — Eigenschaften `BranchI3D`, `BranchOrigin` — Begründung: Jeder Beleg trägt eine Filialzuordnung; diese ist damit fachlich führendes Ordnungsmerkmal.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs, `DoBeforeStoreTrans` — `MandatoryBL.GetNumberGroup(NumberGroupEnum.Helpdesk, branch: entity.Branch)` — Begründung: Zeigt, dass Nummernkreise je Filiale getrennt geführt werden, also die Filiale eine eigenständige Buchungseinheit ist.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Modul `MandatorManagementAppModuleController` mit Recht `UserRightsConst.Administration.MANDATORY` — Begründung: Es existiert eine dedizierte Verwaltungsmaske für Mandanten.
Prüfidee: Zwei Filialen anlegen, in jeder eine Rechnung erzeugen; die vergebenen Rechnungsnummern müssen
aus dem jeweils der Filiale zugeordneten Nummernkreis stammen.
Tracelinks: SyRS-14, SyRS-21, SwRS-14
Konsolidierung: Kandidat: StRS-02 (Filialbeschränkung ist zugleich ein Berechtigungskonzept; im Zielsystem sollte
"Organisationseinheit" ein einziges, quer verwendbares Konzept sein, statt je Modul eigene Filialprüfungen).
Status: belegt
```
## StRS-02
```
ID: StRS-02
Titel: Rollen- und rechtebasierter Zugriff auf Funktionen und Daten
Ebene: StRS
Typ: Sicherheit
Akteur: Systemadministrator / Rechteverwalter
Vorbedingung: Ein Benutzerkonto (`AppUser`) ist angelegt und Rechtegruppen sind gepflegt.
Fakt: Rechte sind als numerische IDs (`I3D`) in der Tabelle `Sichrech` gespeichert und in
`UserRightsConst.cs` (2819 Zeilen) als Konstanten abgebildet. Die Business-Logik prüft sie
durchgängig, z. B. `appUser.HasUserRight(UserRightsConst.Sales.Customer.Helpdesk.ADD_NEW_HELPDESK)`
mit Abbruch und Fehlermeldung bei fehlendem Recht.
Aussage: Das System soll den Zugriff auf jede fachliche Aktion über ein zentrales, granulares
Rechtemodell steuern, damit Aufgabentrennung und Vertraulichkeit im Unternehmen durchsetzbar sind.
Ergebnis: Eine Aktion ohne zugehöriges Recht wird abgewiesen; der Benutzer erhält eine erklärende Meldung.
Belege:
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs — zentraler Rechtekatalog, Klasse `UserRightsConst` — Begründung: Definiert den vollständigen Satz der im System durchgesetzten Rechte-IDs.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs, `CheckUserRigths` (Z. 418–466) — `return Result.AsError("Sie haben nicht das Recht \"Helpdesks anzulegen\".", DefaultMessageCodes.RightCheckFailed);` — Begründung: Zeigt die serverseitige Durchsetzung, nicht nur eine UI-Ausblendung.
- [PRIMÄR] src/backend/Centron.DAO/Mappings/Administration/AppRightMaps.cs — `Table("Sichrech")` — Begründung: Belegt die persistente Ablage des Rechtekatalogs in der Datenbank.
- [KONTEXT] CentronRights.md — Beschreibung der Helpdesk-, Kalender- und Auslastungsrechte inkl. des Konzepts "restricting right" — Begründung: Fachliche Erläuterung der Rechtesemantik durch die Entwicklung selbst.
Prüfidee: Einem Benutzer das Recht `ADD_NEW_HELPDESK` entziehen; ein Anlageversuch über UI *und* über die
REST-Schnittstelle muss beidesmal mit Meldecode `RightCheckFailed` scheitern.
Tracelinks: SyRS-09, SyRS-10, SyRS-20, SwRS-09
Konsolidierung: Kandidat: StRS-03 (Rechte und Lizenzen wirken in `ModuleRegistration.cs` als UND-Verknüpfung auf
dieselbe Sichtbarkeitsentscheidung; im Zielsystem als zwei getrennte Policies mit einem
gemeinsamen Auswertungspunkt zusammenzuführen).
Status: belegt
```
## StRS-03
```
ID: StRS-03
Titel: Lizenzabhängiger Funktionsumfang (Modul- und Nutzerlizenzierung)
Ebene: StRS
Typ: funktional
Akteur: Hersteller (NEXOWARE Systems GmbH) / Kunde als Lizenznehmer
Vorbedingung: Eine Lizenzdatei/Lizenzserver-Anbindung ist konfiguriert.
Fakt: Jedes Modul in `ModuleRegistration.cs` ist mit einem Lizenz-GUID-Check verknüpft
(`LicenseManager.Instance.HasLicense(LicenseGuids.X) || ... HasLicense(LicenseGuids.Centron)`).
`LicenseManager.CheckLicense` prüft zusätzlich beim Login `count`, `valid until date` und
`valid until version` und bricht mit `DefaultMessageCodes.LicenseMaximumReached` ab.
Aussage: Das System soll den nutzbaren Funktionsumfang und die Zahl gleichzeitiger Nutzer je Anwendung
anhand erworbener Lizenzen begrenzen, damit das Produkt modular vermarktet werden kann.
Ergebnis: Nicht lizenzierte Module erscheinen nicht in der Anwendung; bei Überschreiten der Lizenzanzahl
wird die Anmeldung mit "Die maximale Anzahl an Lizenzen wurde erreicht." abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, `CheckLicense` — `if (currentlyUsedLicenses >= maxNumberOfLicenses) results.Add(Result<Guid>.AsError("Die maximale Anzahl an Lizenzen wurde erreicht.", DefaultMessageCodes.LicenseMaximumReached));` — Begründung: Erzwungene Nutzerobergrenze zur Laufzeit.
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Konstruktor `ModuleRegistration()` — je Modul ein `moduleFeatureCheck` mit `LicenseManager.Instance.HasLicense(...)` — Begründung: Lizenz entscheidet über die Registrierung des Moduls in der Anwendung.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/ApplicationKind.cs — je Anwendung `LicenseGuid`, `LicenseUsageKind` (`PerUser` / `PerUserAndPerMachine`), `ExpirationKind` — Begründung: Definiert das Zählmodell der Floating-Lizenzen.
- [KONTEXT] docs/reference/security/licensing-system.md — "Unsere Lizenzen sind einfach nur GUIDs … jede Lizenz kann einen `count`, ein `valid until date` und eine `valid until version` haben" — Begründung: Herstellerdokumentation des Lizenzmodells.
Prüfidee: Lizenzanzahl für `ServiceBoard` auf 1 setzen; ein zweiter gleichzeitiger Login eines anderen
Benutzers muss mit Meldecode `LicenseMaximumReached` abgewiesen werden.
Tracelinks: SyRS-07, SyRS-09, SwRS-11
Konsolidierung: Kandidat: StRS-02 (siehe dort).
Status: belegt
```
## StRS-04
```
ID: StRS-04
Titel: Durchgängige Belegkette vom Angebot bis zur Rechnung
Ebene: StRS
Typ: funktional
Akteur: Vertriebsmitarbeiter / Sachbearbeiter Auftragsabwicklung
Vorbedingung: Ein Kunde (`Customer`) ist im Adressstamm angelegt.
Fakt: Die Objektart-Enumeration `CentronObjectKindNumeric` definiert `OfferClass = 1` ("Angebot"),
`OrderClass = 2` ("Auftrag"), `DeliveryListClass = 3` ("Lieferschein"), `InvoiceClass = 4`
("Rechnung"), `PickupListClass = 5` ("Abholschein"), `CreditVoucherClass = 6` ("Gutschrift").
`ReceiptProgressionBL` ermittelt per SQL Vorgänger- und Nachfolgebelege
(`CreateOriginReceiptsSql` / `CreateFollowUpReceiptsSql`), `ReceiptBL.ForwardReceipt<TReceipt,TReceiptItem>`
führt einen Beleg in den nächsten Belegtyp über.
Aussage: Das System soll den Verkaufsprozess als verkettete Belegfolge abbilden, sodass aus einem Angebot
ein Auftrag, daraus ein Lieferschein und daraus eine Rechnung entstehen kann und die Herkunft
jederzeit rückverfolgbar bleibt.
Ergebnis: Zu jedem Beleg sind Ursprungs- und Folgebelege abrufbar; Positionen werden mit Mengenübernahme
weitergeführt.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs — Enumwerte 1–6 mit `[Description("Angebot")]` … `[Description("Gutschrift")]` — Begründung: Definiert die Belegarten samt fachlicher Benennung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs, `GetRelatedItemsForObject` / `CreateOriginReceiptsSql` — SQL über `AufKopf`, `LiefKopf`, `RechKopf`, Spalten `UrsprungI3D`, `UrsprungArt` — Begründung: Belegt die persistierte Vorgänger-Nachfolger-Beziehung in der Datenbank.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `ForwardReceipt<TReceipt, TReceiptItem>` (Z. 1548) und `CanForwardReceiptsInto` (Z. 1350) — Begründung: Implementiert die Weiterführung inkl. Prüfung, in welche Belegarten überführt werden darf.
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 9951 — `return Result.AsError("Es wurden Positionen entfernt die bereits weiterverarbeitet waren.");` — Begründung: Fehlermeldung belegt, dass die Weiterverarbeitung den Bearbeitungsspielraum am Vorgängerbeleg einschränkt.
Prüfidee: Angebot anlegen → in Auftrag überführen → Lieferschein → Rechnung; anschließend am Auftrag die
Belegprogression abrufen: Sie muss Angebot als Ursprung und Lieferschein/Rechnung als Folgebelege ausweisen.
Tracelinks: SyRS-11, SyRS-15, SyRS-16, SwRS-16, SwRS-17
Konsolidierung: nein
Status: belegt
```
## StRS-05
```
ID: StRS-05
Titel: Belege sind nachvollziehbar abschließbar und stornierbar
Ebene: StRS
Typ: funktional
Akteur: Sachbearbeiter Auftragsabwicklung / Buchhaltung
Vorbedingung: Ein Beleg existiert im Status "offen".
Fakt: `ReceiptState` definiert genau drei Zustände: `Active = 1` ("offen"), `Completed = 2`
("abgeschlossen"), `Canceled = 3` ("storniert"). `ReceiptBL.UpdateReceiptIsPaid` verweigert
Änderungen an stornierten Belegen mit expliziter Meldung.
Aussage: Das System soll für jeden Beleg einen fachlichen Lebenszyklus mit den Zuständen offen,
abgeschlossen und storniert führen, damit abgeschlossene Geschäftsvorfälle nicht unbemerkt
verändert werden.
Ergebnis: Ein stornierter Beleg ist gegen nachträgliche Zahlungsstatusänderungen gesperrt.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs — Enum mit `[Description("offen")] Active = 1`, `Completed = 2`, `Canceled = 3` sowie `GetReceiptStateString` — Begründung: Definiert den vollständigen Zustandsraum eines Belegs.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 4937 — `return Result<IReceiptBase>.AsError($"Der Beleg {receiptI3D} ({receiptKind.GetDescription()}) wurde stoniert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden.", ...);` — Begründung: Durchgesetzte Zustandsregel (Storno sperrt Zahlungsstatusänderung).
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs — `public virtual ReceiptState State { get; set; }` — Begründung: Der Zustand ist persistiertes Attribut jedes Belegs.
Prüfidee: Rechnung stornieren, anschließend "als bezahlt markieren" aufrufen; der Aufruf muss mit der oben
zitierten Fehlermeldung scheitern.
Tracelinks: SyRS-12, SwRS-16
Konsolidierung: nein
Status: belegt
```
## StRS-06
```
ID: StRS-06
Titel: Vertragsbasierte wiederkehrende Abrechnung
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung / Vertragsverwaltung
Vorbedingung: Ein Vertrag (`ReceiptContractHead`) mit Abrechnungsparametern ist erfasst.
Fakt: `BillingIntervalKinds` definiert `Daily = 0`, `Monthly = 1`, `Yearly = 2`, `Quarterly = 3`;
`BillingKinds` definiert `Billingadvance = 0` ("vorschüssig") und `Billingarrear = 1`
("nachschüssig"); `ContractCalculationKind` unterscheidet `Auto`, `Need` und `Manual`.
`AutomaticFacturaBL.Contracts` rechnet Intervalle in Monatswerte um
(`Yearly → *12`, `Quarterly → *3`) und erzeugt daraus Rechnungspositionen.
Aussage: Das System soll wiederkehrende Vertragsleistungen automatisiert und in konfigurierbaren Intervallen
vor- oder nachschüssig fakturieren, damit Serviceverträge ohne manuelle Rechnungsstellung
abgerechnet werden können.
Ergebnis: Für fällige Verträge werden Rechnungen mit dem korrekten Berechnungszeitraum erzeugt.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingIntervalKinds.cs — Enum mit `[Description("Tag(e)")] Daily = 0` … `[Description("Quartal(e)")] Quarterly = 3` — Begründung: Definiert den erlaubten Intervallraum der Vertragsabrechnung.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/BillingKind.cs — `[Description("vorschüssig")] Billingadvance = 0`, `[Description("nachschüssig")] Billingarrear = 1` — Begründung: Definiert die zeitliche Abrechnungsrichtung als Geschäftsregel.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs, Z. 1101–1116 — `switch (billingParam.BillingIntervalKind) { case Yearly: invoiceMonthBillingInterval = billingParam.BillingIntervalDuration * 12; case Quarterly: … * 3; }` — Begründung: Konkrete, durchgesetzte Umrechnung des Abrechnungsintervalls.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Modul "Vertragsabrechnung" (`AutomatedBillingAppModuleController`, Recht `UserRightsConst.Sales.AUTOMATED_BILLING`, Lizenz `LicenseGuids.ContractBilling`) — Begründung: Es existiert eine dedizierte Anwendermaske für diesen Geschäftsprozess.
Prüfidee: Vertrag mit Intervall "Quartal(e)", Dauer 1, vorschüssig anlegen; die automatische Abrechnung muss
einen Berechnungszeitraum von genau 3 Monaten ab Periodenbeginn erzeugen.
Tracelinks: SyRS-32, SyRS-33, SwRS-21
Konsolidierung: Kandidat: StRS-10 (Vertragsabrechnung, Pauschalabrechnung und vereinfachte Ticketabrechnung erzeugen
jeweils eigenständig Rechnungen aus Leistungen; im Zielsystem als ein Abrechnungsservice mit
austauschbaren Mengenquellen zusammenzuführen).
Status: belegt
```
## StRS-07
```
ID: StRS-07
Titel: Kontingentverwaltung innerhalb von Verträgen
Ebene: StRS
Typ: funktional
Akteur: Servicemanager / Buchhaltung
Vorbedingung: Ein Vertrag mit hinterlegtem Kontingent besteht.
Fakt: `ContingentKinds` unterscheidet `Hour = 0` ("Stunde") und `Money = 1` ("Geld");
`ContingentLimitKinds` unterscheidet `Percent` und `Absolute`; die Abrechnungslogik wertet
`Overbooking` (Überbuchung) und `RestTake` / `KontingentRestMitnehmen` (Restübertrag) aus und
kennt über `DifferContingentInterval` vier Fälle abweichender Kontingentintervalle.
Aussage: Das System soll Leistungskontingente in Stunden oder Geldwert je Vertrag führen, deren Verbrauch
gegen Grenzwerte prüfen und Überbuchung sowie Restübertrag in die Folgeperiode regelbasiert
behandeln, damit Servicepauschalen korrekt verrechnet werden.
Ergebnis: Verbrauchte Kontingente werden gebucht; überschreitender Verbrauch wird gemäß Vertragsregel
entweder abgerechnet oder abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/ContingentKinds.cs — `[Description("Stunde")] Hour = 0`, `[Description("Geld")] Money = 1` — Begründung: Definiert die zwei zulässigen Kontingentbemessungen.
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/BillingCenter/Contracts/DifferContingentInterval.cs — `none, interimMajorToContract, headMajorToContract, interimMinorToContract, headMinorToContract` — Begründung: Kodifiziert die Sonderfälle, wenn das Kontingentintervall vom Vertragsintervall abweicht.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.Contracts.cs, Z. 1146–1234 — Auswertung von `contractContingent.DifferContingentIntervalDuration`, `Overbooking`, `RestTake` und Berechnung von `vertragZuordnung.KontingentWert` — Begründung: Enthält die durchgesetzte Kontingentberechnung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Einstellungsseite `ContigentSettingsController` (Namensraum `…Finances.Contracts.Settings.Contigents`) — Begründung: Es gibt eine eigene Konfigurationsmaske für Kontingente.
Prüfidee: Vertrag mit Monatskontingent 10 Stunden, `RestTake = true`, Verbrauch 6 Stunden in Periode 1:
Periode 2 muss ein verfügbares Kontingent von 14 Stunden ausweisen.
Tracelinks: SyRS-32, SwRS-21
Konsolidierung: nein
Status: belegt
```
## StRS-08
```
ID: StRS-08
Titel: Serviceticket-Bearbeitung (Helpdesk) als zentraler Serviceprozess
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker / Servicedisponent / Kunde
Vorbedingung: Ein Kunde ist erfasst; Ticketstatus, -typen und -kategorien sind konfiguriert.
Fakt: Die Entität `Helpdesk` wird über `HelpdeskBL` verwaltet; Ticketstatus sind als Stammdaten in der
Tabelle `hlpdsk_status` (Entität `HelpdeskState`) frei konfigurierbar. Es existieren mindestens
41 spezialisierte Business-Logik-Klassen im Verzeichnis `Sales/Support` (u. a. Eskalation,
Weiterleitung, Historie, Mailanbindung, Zeiterfassung, Checklisten).
Aussage: Das System soll Serviceanfragen als Tickets mit konfigurierbarem Status, Kategorie, Priorität,
Fälligkeit, verantwortlicher Person und Bearbeiterkreis führen, damit Serviceleistungen
nachvollziehbar disponiert und abgerechnet werden können.
Ergebnis: Jede Serviceanfrage ist als Ticket dokumentiert, einem Kunden und Bearbeiter zugeordnet und
besitzt eine lückenlose Statushistorie.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs — Klasse `HelpdeskBL` mit `Save`, `CheckRights`, `DoBeforeStoreTrans`, `SetHelpdeskAction` — Begründung: Zentrale, durchgesetzte Ticketlogik.
- [PRIMÄR] src/backend/Centron.DAO/Mappings/CustomerArea/Support/HelpdeskStateBaseMaps.cs — `Table("hlpdsk_status")`, Spalten `Bezeichnung`, `Beschreibung`, `Status` — Begründung: Ticketstatus sind Stammdaten, nicht fest kodiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/ (41 `*BL.cs`-Dateien, u. a. `HelpdeskCloseBL.cs`, `HelpdeskEscalation`, `HelpdeskForwardBL.cs`, `HelpdeskHistoryBL.cs`) — Begründung: Umfang und Ausdifferenzierung belegen den Helpdesk als Kernprozess, nicht als Randfunktion.
- [KONTEXT] CentronRights.md, Abschnitt "Helpdesk" (18 nummerierte Rechtegruppen) — Begründung: Fachliche Beschreibung des Ticketprozesses aus Herstellersicht.
Prüfidee: Ticket anlegen, Status ändern, weiterleiten, schließen; die Ticket-Historie muss für jede dieser
Aktionen einen Eintrag mit altem und neuem Wert enthalten.
Tracelinks: SyRS-27, SyRS-28, SyRS-29, SyRS-30, SwRS-19
Konsolidierung: nein
Status: belegt
```
## StRS-09
```
ID: StRS-09
Titel: Zeiterfassung mit direktem Abrechnungsbezug
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker / Buchhaltung
Vorbedingung: Ein Ticket existiert; dem Mitarbeiter ist ein Leistungsartikel zugeordnet.
Fakt: Die Entität `HelpdeskTimer` führt `Start`, `Stop`, `Calculable` (abrechenbar), `Article`,
`Contract`, `BillingStateI3D` sowie die Zuordnungsfelder `OrderAssetItemI3D`,
`DeliveryListAssetItemI3D`, `InvoiceAssetItemI3D` mit der abgeleiteten Eigenschaft
`IsAssignedToAsset`.
Aussage: Das System soll Arbeitszeiten ticketbezogen erfassen, als abrechenbar oder nicht abrechenbar
kennzeichnen, einem Leistungsartikel und optional einem Vertrag zuordnen und die Überführung in
einen Beleg festhalten, damit erbrachte Serviceleistungen verlustfrei fakturiert werden.
Ergebnis: Erfasste Zeiten sind eindeutig einem Ticket, einem Artikel und ggf. einem abrechnenden Beleg
zugeordnet.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Support/HelpdeskTimerArea/HelpdeskTimer.cs — Eigenschaften `Calculable`, `Article`, `Contract`, `InvoiceAssetItemI3D`, `IsAssignedToAsset` — Begründung: Das Datenmodell verbindet Zeiterfassung und Fakturierung strukturell.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskTimerBL.cs, Z. 564–565 — `if (helpdeskTimer.IsAssignedToAsset) return Result<int>.AsError("Die Helpdesk Zeit wurde einem Beleg zugewiesen. Löschen ist nicht möglich.");` — Begründung: Abrechnungsschutz ist erzwungen.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Modul "Vereinfachte Ticketabrechnung" (`TimerBillingAppModuleController`) — Begründung: Dedizierte Maske zur Überführung von Zeiten in Rechnungen.
- [KONTEXT] CentronRights.md, Abschnitt 7 "Zeiten bearbeiten" inkl. 7.1 "nur eigene Zeiten" und 8/9 (Verschieben/Löschen nur, "if the ticket is not part of a receipt") — Begründung: Bestätigt die Abrechnungsschutzregel fachlich.
Prüfidee: Zeit erfassen, in eine Rechnung überführen, anschließend die Zeit löschen wollen — der Löschversuch
muss mit der zitierten Meldung scheitern.
Tracelinks: SyRS-31, SwRS-20
Konsolidierung: Kandidat: StRS-10
Status: belegt
```
## StRS-10
```
ID: StRS-10
Titel: Abrechnung erbrachter Leistungen über mehrere Abrechnungsverfahren
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung
Vorbedingung: Abrechenbare Leistungen (Zeiten, Lieferscheine, Aufträge, Verträge) liegen vor.
Fakt: Die Modulregistrierung führt im Bereich "Abrechnung" fünf eigenständige Module:
Pauschalabrechnung (`FlatRateProjectAppModuleController`), Provisionsauswertung,
Provisionsschema-Verwaltung, Vereinfachte Ticketabrechnung (`TimerBillingAppModuleController`)
und Vertragsabrechnung (`AutomatedBillingAppModuleController`) — jeweils mit eigenem Recht und
eigener Lizenz. `ReceiptBL.CreateNewReceiptForHelpdekTimers` und `AutomaticFacturaBL` erzeugen
unabhängig voneinander Belege.
Aussage: Das System soll mehrere Abrechnungsverfahren nebeneinander anbieten (Pauschale, Zeitabrechnung,
Vertragsabrechnung, Provision), damit unterschiedliche Geschäftsmodelle des Kunden bedient werden.
Ergebnis: Aus jeder Leistungsquelle kann ein Verkaufsbeleg erzeugt werden.
Belege:
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "c-entron Module: Abrechnung" — fünf `ModuleRegistrationItem.For<…>` Einträge — Begründung: Belegt die parallele Existenz getrennter Abrechnungswege.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CreateNewReceiptForHelpdekTimers(IList<int> timerI3Ds, TimerBillingSettingsDTO settings, AppUser currentUser)` (Z. 5295) — Begründung: Eigener Erzeugungspfad für zeitbasierte Belege.
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs, `SearchBillingDeliveryLists` / `SearchBillingOrders` — Begründung: Zweiter, unabhängiger Erzeugungspfad für belegbasierte Sammelabrechnung.
Prüfidee: Denselben Kunden über Vertragsabrechnung und über vereinfachte Ticketabrechnung abrechnen; beide
Wege müssen gültige Rechnungen erzeugen, ohne dass Leistungen doppelt fakturiert werden.
Tracelinks: SyRS-32, SyRS-33, SwRS-21
Konsolidierung: Kandidat: StRS-06, StRS-09 — die fünf Abrechnungsmodule bilden dieselbe fachliche Grundfunktion
("Leistung → Rechnungsposition") mit unterschiedlichen Mengenquellen ab und sind im Zielsystem
vorrangig zu konsolidieren.
Status: belegt
```
## StRS-11
```
ID: StRS-11
Titel: Kundenportal zur Selbstbedienung
Ebene: StRS
Typ: funktional
Akteur: Endkunde (Web-Account)
Vorbedingung: Für den Kunden ist ein Web-Account im Adressstamm angelegt.
Fakt: Die Blazor-Anwendung `CentronNexus` stellt unter `WebCart/` u. a. `CustomperPortalHomePage.razor`,
`CustomerTicketDetailsPage.razor`, `CustomerTicketHistoryPage.razor`, `ReceiptsOverview.razor`,
`ContractsOverview.razor` und `CustomerPortalFormsPage.razor` bereit. Die Anmeldung erfolgt über
`/auth/customer` mit `WebLoginType.Customer` gegen `WebAccountAuthenticator`.
Aussage: Das System soll Endkunden ein Webportal bereitstellen, in dem sie eigene Tickets, Belege und
Verträge einsehen sowie Tickets erstellen können, damit Serviceanfragen ohne Telefonkontakt
entgegengenommen werden.
Ergebnis: Der Kunde meldet sich mit Web-Account an und sieht ausschließlich die ihm zugeordneten Daten.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs — `WebLoginType.Customer => new WebAccountAuthObject { … }` und `GetFromWebAccountAuth → new WebAccountAuthenticator(...)` — Begründung: Eigener, getrennter Authentifizierungspfad für Kunden.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs, `CheckWebRights` (Z. 468–500) — Prüfung von `WebAccountRightsConst.WEBRIGHT_CREATEREQUEST`, `WEBRIGHT_EDITONLYOWNREQUESTS`, `WEBRIGHT_CLOSEALLEREQUESTS` — Begründung: Kundenrechte sind serverseitig getrennt vom Mitarbeiterrechtemodell durchgesetzt.
- [SEKUNDÄR] src/nexus/CentronNexus/WebCart/ — Seitenverzeichnis des Kundenportals (Tickets, Belege, Verträge, Formulare, Dokumente) — Begründung: Belegt den Funktionsumfang aus Anwendersicht.
- [KONTEXT] src/nexus/CentronNexus/Shared/Auth/AUTHENTICATION.md, Abschnitt "Customer Portal Login" — Begründung: Herstellerdokumentation der Portaltrennung.
Prüfidee: Mit einem Web-Account anmelden, der nur `WEBRIGHT_EDITONLYOWNREQUESTS` besitzt: Der Zugriff auf ein
Ticket eines anderen Ansprechpartners desselben Kunden muss abgewiesen werden.
Tracelinks: SyRS-01, SyRS-20, SyRS-35, SwRS-10, SwRS-24
Konsolidierung: Kandidat: StRS-02 — es existieren zwei getrennte Rechtekataloge (`UserRightsConst` für Mitarbeiter,
`WebAccountRightsConst` für Kunden) mit teils überlappender Semantik.
Status: belegt
```
## StRS-12
```
ID: StRS-12
Titel: Kundenseitige Bestellung mit mehrstufigem Freigabeprozess
Ebene: StRS
Typ: funktional
Akteur: Endkunde (Besteller, Prüfer, Einkäufer im Kundenunternehmen)
Vorbedingung: Die Lizenz für den Warenkorb ist vorhanden; der Kunde besitzt Sonderpreise.
Fakt: `ReceiptCartState` definiert die Zustände `Created`, `ReadyForCheck`, `Checked`,
`DeclinedByChecker`, `Ordered`, `DeclinedByOrderer`. `ReceiptCartReleaseSystemBL` erzwingt je
Übergang das erwartete Ausgangsstadium und ein spezifisches Web-Recht
(`WEBRIGHT_WEBCART2_CHECK_CART`, `WEBRIGHT_WEBCART2_ORDER_CART`) und versendet je Übergang Mails.
Aussage: Das System soll dem Kunden erlauben, Bedarfe als Warenkorb zu erfassen und diese vor der
Bestellung durch definierte Prüfer- und Einkäuferrollen im Kundenunternehmen freigeben zu lassen,
damit interne Beschaffungsrichtlinien des Kunden eingehalten werden.
Ergebnis: Ein Warenkorb wird erst nach Freigabe durch Prüfer und Einkäufer zur Bestellung; jeder Schritt ist
protokolliert und wird per Mail kommuniziert.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptCartState.cs — Enum plus eingebettetes Mermaid-Zustandsdiagramm des Freigabeprozesses — Begründung: Explizit dokumentierter und im Code verankerter Workflow.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptCartReleaseSystemBL.cs, `UpdateReceiptCartState` — `if (actualState != expectedState) throw new ResultException("Der Warenkorb befindet sich bereits an einem anderen Schritt des Freigabewesens.", DefaultMessageCodes.BadRequest);` — Begründung: Erzwungene Zustandsübergangsprüfung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptCartReleaseSystemBL.cs, `CheckerApproveCart` — `Guard.Not(currentUser.IsWebAccountLogin is false, "Only web-account logins can approve carts.");` — Begründung: Die Freigabe ist ausdrücklich dem Kunden vorbehalten, nicht dem Lieferanten.
- [SEKUNDÄR] README.md, Abschnitt "Contributing / 1. WebCart" — "The webcart is a feature primarily intended for the customers of our customers … The available articles come from the customers 'Sonderpreise'" — Begründung: Fachliche Zielsetzung des Moduls.
Prüfidee: Warenkorb im Zustand `Created` direkt freigeben wollen (ohne `ReadyForCheck`): Der Aufruf muss mit
"Der Warenkorb befindet sich bereits an einem anderen Schritt des Freigabewesens." scheitern.
Tracelinks: SyRS-34, SwRS-18
Konsolidierung: nein
Status: belegt
```
## StRS-13
```
ID: StRS-13
Titel: Elektronische Rechnungsstellung nach ZUGFeRD/XRechnung
Ebene: StRS
Typ: Schnittstelle
Akteur: Buchhaltung / Rechnungsempfänger (auch öffentliche Auftraggeber)
Vorbedingung: Für den Kunden ist ZUGFeRD-Export aktiviert bzw. eine Leitweg-ID hinterlegt.
Fakt: `ReceiptBL.GetLeitwegID(int customerNumber)` liest die `LeitwegID` vom Kunden bzw. — falls
vorhanden — von dessen Firmengruppe. `GetLocalZUGFeRDSetting` liest das Kundenkennzeichen
`ExportZUGFeRDDocument`. Bei aktivem ZUGFeRD verlangt die Reporterzeugung ein PDF:
"Für ZUGFeRD muss ein PDF Dokument über die Rechnung erzeugt werden."
Aussage: Das System soll Ausgangsrechnungen als strukturierte elektronische Rechnung (ZUGFeRD/XRechnung)
inklusive Leitweg-ID erzeugen, damit gesetzliche Vorgaben zur E-Rechnung gegenüber öffentlichen
und privaten Auftraggebern erfüllt werden.
Ergebnis: Für gekennzeichnete Kunden entsteht zusätzlich zum PDF ein normkonformer XML-Datensatz.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `GetLeitwegID` (Z. 3417) und `GetLocalZUGFeRDSetting` (Z. 3438) — Begründung: Kundenbezogene Steuerung des E-Rechnungsausgangs ist implementiert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 3279 — `return Result<ReceiptReportDTO>.AsError("Für ZUGFeRD muss ein PDF Dokument über die Rechnung erzeugt werden.");` — Begründung: Erzwungene Vorbedingung des hybriden ZUGFeRD-Formats.
- [PRIMÄR] src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/InvoiceZugferdBL.cs, `InvoiceZugferdBL.Zugferd10.cs`, src/backend/Centron.BL/DataExchange/EDI/SaleInvoices/Interfaces/XInvoiceVersion3.cs — Begründung: Eigene Implementierung der ZUGFeRD-/XRechnung-Erzeugung.
- [KONTEXT] docs/guides/development/xrechnung.md und docs/reference/zugferd-feldzuordnung-anwender.md — Begründung: Herstellerdokumentation inkl. Feldzuordnung für Anwender.
Prüfidee: Kunde mit `ExportZUGFeRDDocument = true` und gepflegter Leitweg-ID: Der Rechnungsversand muss ein
PDF mit eingebettetem XML erzeugen, dessen `BuyerReference` der Leitweg-ID entspricht.
Tracelinks: SyRS-26, SwRS-22
Konsolidierung: nein
Status: belegt
```
## StRS-14
```
ID: StRS-14
Titel: Übergabe von Buchungs- und Stammdaten an die Finanzbuchhaltung
Ebene: StRS
Typ: Schnittstelle
Akteur: Buchhaltung / Steuerberater
Vorbedingung: Eine Exportkonfiguration (`BookKeepingExportConfiguration`) ist angelegt.
Fakt: `BookKeepingExportBL` erzeugt Exportdateien für Kunden-, Lieferanten-, Kassenbuch- und
Belegbuchungsdaten und führt eine Exporthistorie (`GetBookKeepingExportCustomerReceiptHistory`,
`IsReceiptExported`). Es existieren Format-Implementierungen u. a. für DATEV XML Online 2020
und Abacus.
Aussage: Das System soll Buchungsdaten aus Belegen sowie Debitoren-/Kreditorenstammdaten in
Buchhaltungsformate exportieren und den Exportstand je Beleg festhalten, damit doppelte oder
fehlende Übergaben an die Buchhaltung ausgeschlossen sind.
Ergebnis: Bereits exportierte Belege sind als solche erkennbar und werden nicht erneut übergeben.
Belege:
- [PRIMÄR] src/backend/Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs — `IsReceiptExported(CentronObjectKindNumeric receiptKind, int receiptI3D)` (Z. 209), `ExportCustomerBookingDataFile` (Z. 832) — Begründung: Exportstand ist Teil der durchgesetzten Logik.
- [PRIMÄR] tests/backend/Centron.Tests.BL/DataExchange/BookKeeping/DatevXMLOnline2020/BookKeepingExportDatevXmlOnline_2020Test.cs und .../Abacus/BookKeepingExportAbacusTest.cs — Begründung: Automatisierte Tests belegen die Formatunterstützung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Module "Buchhaltungsexport/-import" (`DataExchangeAppModuleController`, Rechte `BOOKKEEPING_EXPORT`/`BOOKKEEPING_IMPORT`) und "Datev Belegtransfer" (`DatevOnlineAppModuleController`) — Begründung: Anwenderseitige Module für den Prozess.
- [KONTEXT] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs — `BookKeepingExportFinancialYearStartDate: "Contains the financial year start date for the book keeping export."` — Begründung: Wirtschaftsjahr ist konfigurierbarer Parameter des Exports.
Prüfidee: Rechnung exportieren, Export wiederholen: Der zweite Lauf darf die Rechnung nicht erneut in die
Exportdatei aufnehmen, solange sie nicht ausdrücklich zurückgesetzt wurde.
Tracelinks: SyRS-26, SwRS-22
Konsolidierung: nein
Status: belegt
```
## StRS-15
```
ID: StRS-15
Titel: Mahnwesen und Überwachung offener Posten
Ebene: StRS
Typ: funktional
Akteur: Buchhaltung / Debitorenbuchhaltung
Vorbedingung: Es existieren fällige, unbezahlte Rechnungen.
Fakt: Es bestehen Module "Mahnung" (`DunningOverviewAppModuleController`) und "OPOS"
(`OposOverviewAppModuleController`), beide gebunden an das Recht
`UserRightsConst.Controlling.Finances.Dunning`. `ReceiptBL.GetCustomerOrSupplierDunningLevel`
liefert Mahnstufen 0–3, und `CanUserCreateNewReceiptsAtCustomerOrSupplier` blockiert ab einer
konfigurierten Mahnstufe die Neuanlage von Belegen.
Aussage: Das System soll offene Posten überwachen, Mahnstufen je Kunde führen und ab einer definierten
Mahnstufe die Neuanlage weiterer Belege für diesen Kunden verhindern, damit das Ausfallrisiko
begrenzt wird.
Ergebnis: Für einen Kunden mit erreichter Sperrmahnstufe wird die Belegneuanlage mit erklärender Meldung
abgewiesen.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `CanUserCreateNewReceiptsAtCustomerOrSupplier` (Z. 10203–10218) — `if (dunningLevel >= blockOnLevel) return Result.AsError($"Aufgrund der Mahnstufe darf kein neuer Beleg vom Typ \"…\" angelegt werden.");` — Begründung: Direkt durchgesetzte Kreditsperre.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `GetCustomerOrSupplierDunningLevel<TReceipt>` (Z. 10228 ff.) inkl. Kommentar "Should return 0 for 'no dunning-level reached', 1 for 'dunning-level 1' …" — Begründung: Definiert den Wertebereich der Mahnstufe.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Module "Mahnung" und "OPOS" — Begründung: Es existieren dedizierte Anwendermasken.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/Dunning/ und .../Invoices/Opos/ — Begründung: Eigene Business-Logik-Verzeichnisse für Mahnwesen und offene Posten.
Prüfidee: Kunde auf Mahnstufe 3 setzen, Sperrschwelle auf 2 konfigurieren; ein neuer Auftrag für diesen
Kunden muss abgewiesen werden, eine Gutschrift je nach Konfiguration weiterhin möglich sein.
Tracelinks: SyRS-22, SwRS-15
Konsolidierung: nein
Status: belegt
```
## StRS-16
```
ID: StRS-16
Titel: Artikel-, Lager- und Bestandsverwaltung
Ebene: StRS
Typ: funktional
Akteur: Lagerist / Einkäufer
Vorbedingung: Artikelstamm und Lagerorte sind angelegt.
Fakt: Es existieren die Module Artikelverwaltung, Artikelimport, Inventur und Kommissionierung;
`ArticleStockBL` bietet `UpdateArticleStock`, `IncreaseArticleStock`, `GetArticleStockDemands`
und `UpdateArticlePurchasePrice`. Seriennummern werden über `BarCode2`/`BarcodeBL` mit
Zustandsfeld `BarcodeState` geführt.
Aussage: Das System soll Artikelstammdaten, Lagerbestände je Lagerort, Bedarfe, Einkaufspreise und
Seriennummern führen, damit Warenwirtschaft und Bestandsbewertung im Handelsgeschäft abgebildet sind.
Ergebnis: Bestandsveränderungen durch Belege werden bestandsführend gebucht; Inventurdifferenzen sind
erfassbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs — `UpdateArticleStock(int articleI3D, int? articleSecondaryStorageI3D, double quantity)`, `IncreaseArticleStock(...)`, `UpdateArticlePurchasePrice(...)` — Begründung: Bestandsführung ist implementiert und wird von der Belegverarbeitung aufgerufen.
- [PRIMÄR] src/backend/Centron.BL/Warehousing/InventoryManagement/InventoryBL.cs, InventoryNewBL.cs — Begründung: Inventurprozess als eigene Business-Logik.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (CreateNewVersion) — "In der aktuellen Version dieses Belegs sind noch einige Seriennummern aktiv." — Begründung: Seriennummernführung greift steuernd in die Belegbearbeitung ein.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "c-entron Module: Logistik" — Module Artikelimport, Artikelverwaltung, Inventur, Kommissionierung — Begründung: Anwenderseitiger Funktionsumfang.
Prüfidee: Lieferschein mit Menge 5 buchen; der Lagerbestand des Artikels muss anschließend um genau 5
niedriger sein.
Tracelinks: SyRS-11, SwRS-05
Konsolidierung: nein
Status: belegt
```
## StRS-17
```
ID: StRS-17
Titel: Einkaufsprozess mit Lieferantenbelegen
Ebene: StRS
Typ: funktional
Akteur: Einkäufer
Vorbedingung: Ein Lieferant (`Supplier`/`Kreditor`) ist angelegt.
Fakt: Es existieren Entitäts- und Logikbäume für `SupplierOrders`, `SupplierDeliveryLists`,
`SupplierInvoices`, `SupplierCreditVouchers` sowie ein `SupplierReceiptDocument`-Import mit
PDF-Scan-Konfiguration (`SupplierPdfScanConfigs`). `ExternalReceiptNumberAlreadyExists` und
`GetDuplicateSupplierExternalInvoiceReceiptDescription` prüfen auf doppelte
Lieferantenrechnungsnummern.
Aussage: Das System soll den Beschaffungsprozess mit Bestellung, Wareneingang, Lieferantenrechnung und
Lieferantengutschrift abbilden und dabei Doppelerfassungen von Lieferantenrechnungen erkennen,
damit die Kreditorenbuchhaltung korrekt bleibt.
Ergebnis: Eine bereits erfasste externe Rechnungsnummer wird bei erneuter Erfassung als Dublette gemeldet.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, `ExternalReceiptNumberAlreadyExists(string externalNumber)` (Z. 5082) und `GetDuplicateSupplierExternalInvoiceReceiptDescription(string externalInvoiceNumber)` (Z. 5095) — Begründung: Dublettenprüfung ist implementiert.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/SupplierOrders/, .../SupplierDeliveryLists/, .../SupplierInvoices/, .../SupplierCreditVouchers/ — Begründung: Vollständige Belegarten des Einkaufs im Datenmodell.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "c-entron Module: Einkauf" — Module Belegerfassung, Bestellvorschlagsliste, EDI-Verwaltung, Eingang/Kalkulation — Begründung: Anwenderseitiger Funktionsumfang.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Einstellungscontroller `SupplierInvoiceSettingsController`, `SupplierOrderSettingsController`, `SupplierDeliveryListSettingsController`, `SupplierCreditVoucherSettingsController` — Begründung: Belegarten des Einkaufs sind eigenständig konfigurierbar.
Prüfidee: Zwei Lieferantenrechnungen mit identischer externer Rechnungsnummer desselben Lieferanten erfassen;
die zweite Erfassung muss eine Dublettenmeldung erzeugen.
Tracelinks: SyRS-11, SyRS-20, SwRS-17
Konsolidierung: Kandidat: StRS-04 — Kunden- und Lieferantenbelege teilen die Basisklasse `ReceiptBase`, sind aber in
getrennten Modul-, Einstellungs- und Logikbäumen abgebildet.
Status: belegt
```
## StRS-18
```
ID: StRS-18
Titel: Provisionsermittlung für Vertriebsmitarbeiter
Ebene: StRS
Typ: funktional
Akteur: Vertriebsleitung / Personalabrechnung
Vorbedingung: Ein Provisionsschema ist definiert und einem Kunden zugeordnet.
Fakt: Die Entitäten `ReceiptProvisionSchema`, `ReceiptProvisionSchemaItem`,
`ReceiptProvisionSchemaCustomerAssignment`, `ReceiptProvisionEmployeeGoal` und
`ReceiptProvisionEmployeeLevel` bilden Schemata, Kundenzuordnung, Mitarbeiterziele und -stufen ab.
`InvoiceSpecificLogic` liest die Einstellungen `InvoiceAutoProvisionIsActive`,
`InvoiceAutoProvisionEmployee` und `InvoiceAutoProvisionPercent`.
Aussage: Das System soll aus Verkaufsbelegen Provisionen nach konfigurierbaren Schemata, Zielen und Stufen
ermitteln, damit die erfolgsabhängige Vergütung des Vertriebs nachvollziehbar berechnet wird.
Ergebnis: Für jede Rechnung wird — bei aktivierter Automatik — ein Provisionsdatensatz mit dem
konfigurierten Prozentsatz erzeugt.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptProvisionSchema.cs, ReceiptProvisionSchemaItem.cs, ReceiptProvisionSchemaCustomerAssignment.cs, ReceiptProvisionEmployeeGoal.cs, ReceiptProvisionEmployeeLevel.cs — Begründung: Vollständiges Datenmodell der Provisionsermittlung.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs, Z. 469–517 — Auswertung von `ApplicationSettingID.InvoiceAutoProvisionIsActive`, `…Employee`, `…Percent` — Begründung: Automatische Provisionierung ist konfigurierbar und implementiert.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Module Provisionsauswertung, Provisionsschemas verwalten, Provisionsschema-Kundenzuordnung mit den Rechten `Sales.Provision.PROVISION_EVALUATION_MODULE`, `PROVISION_SCHEMA_MANAGEMENT`, `PROVISION_SCHEMA_CUSTOMER_ASSIGNMENT` — Begründung: Anwenderseitige Prozessunterstützung inkl. Aufgabentrennung.
Prüfidee: `InvoiceAutoProvisionIsActive = true`, Prozentsatz 3, Mitarbeiter X; eine neue Rechnung über 1.000 €
muss einen Provisionsdatensatz von 30 € für Mitarbeiter X erzeugen.
Tracelinks: SyRS-20, SwRS-15
Konsolidierung: nein
Status: belegt
```
## StRS-19
```
ID: StRS-19
Titel: Controlling- und Auswertungsfähigkeit über alle Geschäftsbereiche
Ebene: StRS
Typ: funktional
Akteur: Geschäftsführung / Controlling
Vorbedingung: Operative Daten (Belege, Zeiten, Verträge) liegen vor.
Fakt: Die Modulregistrierung führt im Bereich "Controlling/Analytics" die Module Analytics,
Leistungsnachweise, Management Info, Mitarbeiterauslastung, MSP-Auswertung, MSP-Collector,
MSP-Dashboard und Vertragsauswertung, jeweils rechte- und lizenzgebunden. Im Backend existieren
`Centron.BL/Statistics/` mit `ContractEvaluationBL`, `ContractStatisticBL` und
`MspCollectorsBL`.
Aussage: Das System soll Auswertungen zu Umsatz, Mitarbeiterauslastung, Vertragsbestand und
Managed-Services-Kennzahlen bereitstellen, damit die Unternehmenssteuerung auf einer einheitlichen
Datenbasis erfolgen kann.
Ergebnis: Auswertungen sind ohne Export in Drittsysteme innerhalb der Anwendung abrufbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Statistics/ContractStatistics/ContractEvaluationBL.cs, ContractStatisticBL.cs — Begründung: Auswertungslogik im Backend implementiert.
- [PRIMÄR] src/backend/Centron.BL/Statistics/MspCollectors/MspCollectorsBL.cs (referenziert in AutomaticFacturaBL) — Begründung: MSP-Kennzahlen fließen in die Abrechnung ein, sind also produktiv genutzt.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, Region "c-entron Module: Controlling/Analytics" — acht Module — Begründung: Anwenderseitiger Auswertungsumfang.
- [KONTEXT] CentronRights.md, Abschnitt "Mitarbeiterauslastung" inkl. restriktivem Recht "nur eigene Filiale" — Begründung: Auswertungen unterliegen demselben Berechtigungsrahmen wie operative Daten.
Prüfidee: Benutzer mit `RIGHT_MITARBEITERAUSLASTUNGNUREIGENEFILIALE` öffnet die Mitarbeiterauslastung; es
dürfen ausschließlich Mitarbeiter seiner eigenen Filiale angezeigt werden.
Tracelinks: SyRS-10, SwRS-09
Konsolidierung: nein
Status: belegt
```
## StRS-20
```
ID: StRS-20
Titel: Unterstützung datenschutzrechtlicher Betroffenenrechte (DSGVO)
Ebene: StRS
Typ: Sicherheit
Akteur: Datenschutzbeauftragter / Systemadministrator
Vorbedingung: Das DSGVO-Modul ist lizenziert und das Recht `DsgvoModule.ACCESS_DSGVO_MODULE` vergeben.
Fakt: `DataSecurityBL` stellt `DsgvoDeleteRightGetContacts` und `DsgvoDeleteRightDeleteContacts` bereit
und ersetzt gelöschte Kontaktdaten durch den Text
`"DSGVO: Auf Anfrage gelöscht. (Durchgeführt von {0} am {1:d} um {1:t} Uhr)"`. Jeder Zugriff wird
zuvor gegen Rechte geprüft (`return Result.AsError("Insufficient rights!")`).
Aussage: Das System soll das Auffinden und das protokollierte Löschen personenbezogener Ansprechpartnerdaten
auf Betroffenenanfrage unterstützen, damit dem Auskunfts- und Löschanspruch der DSGVO entsprochen
werden kann.
Ergebnis: Betroffene Kontaktdaten sind nach der Ausführung durch einen Löschvermerk mit Bearbeiter und
Zeitstempel ersetzt; ein Löschprotokoll wird geführt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, Z. 26–27 — Konstanten `DsgvoDeletedContactMessage` / `DsgvoDeletedContactMessageWithEmployeeInfo` — Begründung: Belegt Ersetzung statt physischer Löschung inkl. Nachweis der ausführenden Person.
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, `DsgvoDeleteRightDeleteContacts` (Z. 787 ff.) — Transaktionale Ausführung mit `deleteProtocol` — Begründung: Protokollierte, atomare Durchführung.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Modul "c-entron DSGVO" (`CentronDataSecurityAppModuleController`, Lizenz `LicenseGuids.CentronDSGVO`) — Begründung: Eigenständiges, lizenziertes Modul.
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Documents/Dsgvo/OrderProcessingContractOnlinePdfDocumentHandler.cs — Begründung: Auftragsverarbeitungsverträge werden als eigener Dokumenttyp verwaltet.
Prüfidee: Löschanfrage für einen Ansprechpartner ausführen; danach müssen Name und Kontaktdaten durch den
Löschvermerk ersetzt sein und der zugehörige Beleg-/Ticketbezug erhalten bleiben.
Tracelinks: SyRS-45, SwRS-07
Konsolidierung: nein
Status: belegt
```
## StRS-21
```
ID: StRS-21
Titel: Nachvollziehbarkeit fachlicher Änderungen
Ebene: StRS
Typ: nicht-funktional (Zuverlässigkeit / Nachweisbarkeit)
Akteur: Revision / Führungskraft / Support
Vorbedingung: Ein Datensatz wird geändert.
Fakt: Die Entität `ChangeLog` speichert `ObjectI3D`, `ObjectKind`, `Property`, `OldValue`, `NewValue`,
`Date` und `AppUser` in der Tabelle `ChangeLog`. Zusätzlich existieren fachspezifische Historien:
`ReceiptLog`, `ReceiptHistoryEntry`, `HelpdeskHistoryBL`, `ArticleLogBL`, `HelpdeskTimerLogBL`.
`ReceiptBase` führt außerdem `CreatedByI3D`, `CreatedAt`, `ChangedByI3D`, `ChangedAt`,
`CreatedThroughApplicationVersion`, `ChangedThroughApplication`.
Aussage: Das System soll fachlich relevante Änderungen mit altem Wert, neuem Wert, Zeitpunkt, Benutzer und
auslösender Anwendung protokollieren, damit Geschäftsvorfälle im Nachhinein nachvollziehbar bleiben.
Ergebnis: Zu jedem geänderten Objekt lässt sich die Änderungshistorie anzeigen.
Belege:
- [PRIMÄR] src/backend/Centron.Entities/Entities/ChangeTracking/ChangeLog.cs und src/backend/Centron.DAO/Mappings/ChangeTracking/ChangeLogMaps.cs — `Table("ChangeLog")`, Spalten `OldValue`, `NewValue`, `Property` (je `Length(255)`) — Begründung: Generisches Änderungsprotokoll ist persistiert.
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs — `CreatedByI3D`, `CreatedAt`, `ChangedByI3D`, `ChangedAt`, `ChangedThroughApplication` — Begründung: Herkunftsnachweis auf jedem Beleg.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs, `SetHelpdeskAction` — schreibt "Status wurde von '…' auf '…' geändert." über `HelpdeskHistoryBL.SaveHelpdeskAction` — Begründung: Statuswechsel wird zwingend historisiert.
- [KONTEXT] docs/guides/database/database-conventions.md, Abschnitt "Standard Tracking Columns" — `CreatedByI3D`, `CreatedDate`, `ChangedByI3D`, `ChangedDate`, `IsDeleted`, `DeletedByI3D`, `DeletedDate` als Pflichtspalten — Begründung: Vorgabe, dass Nachvollziehbarkeit systemweite Konvention ist.
Prüfidee: Fälligkeitsdatum eines Tickets ändern; die Ticket-Historie muss einen Eintrag "Fälligkeitsdatum
wurde geändert" mit altem und neuem Datum sowie dem ausführenden Benutzer enthalten.
Tracelinks: SyRS-29, SyRS-37, SwRS-07
Konsolidierung: Kandidat: die vier parallelen Historienmechanismen (`ChangeLog`, `ReceiptLog`,
`ReceiptHistoryEntry`, Helpdesk-Historie) bilden dieselbe fachliche Anforderung ab und sind im
Zielsystem zu einem Audit-Trail zusammenzuführen.
Status: belegt
```
## StRS-22
```
ID: StRS-22
Titel: Digitale Freigabe und Unterzeichnung von Dokumenten durch den Kunden
Ebene: StRS
Typ: funktional
Akteur: Kunde / Vertriebsmitarbeiter
Vorbedingung: Die Signaturlizenz ist vorhanden und die c-entron-Nexus-URL ist konfiguriert.
Fakt: `ReceiptBL.SendSignAcceptance` und `SendSignDocument` erzeugen ein Token für ein geteiltes
Dokument und versenden es; ohne Lizenz bzw. ohne konfigurierte Nexus-URL wird abgebrochen
("Sie besitzen nicht die Lizenz für das Signieren", "Die c-entron Nexus Url ist nicht gesetzt").
In `CentronNexus` existieren `DocumentSigningPage.razor`, `IsolatedSignaturePad.razor` sowie
`SharedDocumentSignPage.razor` / `SharedDocumentAcceptancePage.razor`.
`WebReceiptState` kennt die Zustände `WebOfferSign`, `WebOfferSignedWithoutSignature`,
`AcceptFullWebReceipt`, `AcceptWebReceiptWithChangeRequests`, `Rejected`.
Aussage: Das System soll Angebote und Dokumente über einen Weblink zur Ansicht, Annahme und handschriftlichen
Unterzeichnung durch den Kunden bereitstellen, damit Auftragsbestätigungen ohne Medienbruch
eingeholt werden können.
Ergebnis: Der Annahme-/Signaturstatus eines Web-Belegs ist im ERP sichtbar und auslösendes Ereignis für die
Weiterverarbeitung.
Belege:
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs — Zustände `InProcess`, `AcceptFullWebReceipt`, `AcceptWebReceiptWithChangeRequests`, `Rejected`, `SendToCustomer`, `FirstLoaded`, `WebOfferSign`, `WebReceiptShutDown`, `WebOfferSignedWithoutSignature` — Begründung: Kodifiziert den kundenseitigen Freigabelebenszyklus.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Z. 7032–7133 — `SendSignAcceptance`, `SendSignDocument` inkl. Lizenz- und Konfigurationsprüfung — Begründung: Serverseitig erzwungene Vorbedingungen des Signaturversands.
- [SEKUNDÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor — Begründung: Anwenderseitige Signaturoberfläche.
- [KONTEXT] Commit 89ccfd650d "Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance) (#128)" und cf27c00580 "Ticket 160807 - Fix c-sign document preview and signing document (#70)" — Begründung: Aktive Weiterentwicklung mit Ticketbezug belegt die geschäftliche Relevanz.
Prüfidee: Angebot per C-Sign versenden; nach kundenseitiger Unterzeichnung muss der Web-Beleg-Status auf
`WebOfferSign` stehen und die Signatur am Dokument hinterlegt sein.
Tracelinks: SyRS-46, SwRS-24
Konsolidierung: nein
Status: belegt
```
## StRS-23
```
ID: StRS-23
Titel: Anbindung externer Fach- und Dienstleistersysteme
Ebene: StRS
Typ: Schnittstelle
Akteur: Systemadministrator / Fachabteilungen
Vorbedingung: Zugangsdaten des jeweiligen Drittsystems sind konfiguriert.
Fakt: Unter `src/apis/` existieren eigenständige Integrationsassemblies für ITscope, Icecat, GLS,
Shipcloud, FinAPI, EGIS, COP und eb-Interface. Weitere Konnektoren finden sich unter
`Centron.BL/DataExchange/Connectors`, `.../Rmm`, `.../TanssInterfaces`, `.../TelekomDive`,
`.../DocuForm`, sowie ein separates Projekt `Centron.Api.docuFORM`. In der Modulregistrierung sind
`ICEcatSettingsController`, `GlsSettingController`, `ShipcloudSettingController`,
`DocBeeConnectorSettingsController`, `DocuFormApiSettingsController` und
`OnlineBankingConfigurationSettingsController` registriert.
Aussage: Das System soll Artikeldaten, Versanddienstleister, Bankdaten, Monitoring- und Dokumenten­systeme
über konfigurierbare Konnektoren anbinden, damit Fremddaten ohne manuelle Doppelerfassung in die
Geschäftsprozesse einfließen.
Ergebnis: Externe Daten (z. B. Artikelstammdaten, Sendungsverfolgung, Kontoumsätze) sind in der Anwendung
verfügbar.
Belege:
- [PRIMÄR] src/apis/ — acht Projektverzeichnisse (Centron.APIs.ITscopeDataAccess, .IcecatDataAccess, .FinAPI, .CopDataAccess, .EgisDataAccess, Centron.Api.Gls, Centron.Api.Shipcloud, Centron.Api.EbInterface) — Begründung: Eigenständige, kompilierte Integrationsschichten.
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Settings/ApplicationSettingDefinitions.cs — `ITscopeApiKey: "The API key for ITscope."`, `IsITscopeArticleSearchActive: "Whether the ITscope article search is active."` — Begründung: Konfigurierbarkeit der Integration.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs, `GetSettingsWithoutModule()` — Einstellungscontroller für GLS, Shipcloud, ICEcat, DocBee, docuFORM, Online-Banking — Begründung: Anwenderseitige Konfigurationsoberflächen je Konnektor.
- [KONTEXT] tests/apis/ — vier Testprojekte für COP, EGIS, Icecat, ITscope — Begründung: Die Integrationen sind testabgedeckt und damit produktiv relevant.
Prüfidee: ITscope-API-Key hinterlegen und `IsITscopeArticleSearchActive` aktivieren; die Artikelsuche im
Beleg muss anschließend Treffer aus ITscope liefern.
Tracelinks: SyRS-47, SwRS-27
Konsolidierung: nein
Status: belegt
```
## StRS-24
```
ID: StRS-24
Titel: Zentrale Authentifizierung inklusive Unternehmens-SSO und Zwei-Faktor-Verfahren
Ebene: StRS
Typ: Sicherheit
Akteur: Systemadministrator / alle Benutzer
Vorbedingung: Ein Benutzerkonto existiert; das gewünschte Authentifizierungsverfahren ist konfiguriert.
Fakt: `AuthenticatorFactory` wählt anhand der Systemeinstellung `SystemAuthenticationMethod`
(`None`, `Basic`, `ActiveDirectory`, `OpenIdConnect`) und der benutzerbezogenen
`AuthentificationKind` einen Authenticator und kapselt ihn in einen `FallbackAuthenticator`.
`TwoFactorAuthBL` validiert nach erfolgreicher Primärauthentifizierung einen zweiten Faktor
(`EmailTwoFactorValidator`, `RadiusTwoFactorValidator`).
Aussage: Das System soll Anmeldungen wahlweise über lokale Zugangsdaten, Active Directory oder
OpenID Connect (Microsoft Entra ID) zulassen und optional einen zweiten Faktor verlangen, damit
das Unternehmen sein bestehendes Identitätsmanagement weiternutzen kann.
Ergebnis: Nur nach erfolgreicher Primär- und ggf. Zweitfaktor-Prüfung wird eine Sitzung (Ticket) ausgestellt.
Belege:
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/AuthenticatorFactory.cs, `GetFromBasicAuth` / `GetFromOpenIdConnectAuth` — Begründung: Zentrale, konfigurationsgesteuerte Verfahrensauswahl.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/BasicAuthenticator.cs, `AuthenticateInternal` — Aufruf `_twoFactorAuthBL.ValidateTwoFactor(...)`; bei Fehlschlag `Result<LoggedInUser>.AsError("Die Zwei-Faktor-Authentifizierung ist fehlgeschlagen.", DefaultMessageCodes.TwoFactorAuthFailed)` — Begründung: Zweiter Faktor ist erzwungener Bestandteil der Anmeldung.
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TwoFactor/ — `EmailTwoFactorValidator.cs`, `RadiusTwoFactorValidator.cs`, `RadiusClient.cs` — Begründung: Zwei implementierte Zweitfaktorverfahren.
- [KONTEXT] src/nexus/CentronNexus/Shared/Auth/AUTHENTICATION.md — vollständige Ablaufbeschreibung inkl. Microsoft-SSO und Outlook-Add-in — Begründung: Herstellerdokumentation der Anmeldeverfahren.
Prüfidee: `SystemAuthenticationMethod = OpenIdConnect` setzen und für einen Benutzer keine verknüpfte
Microsoft-Kennung hinterlegen: Die SSO-Anmeldung muss scheitern, die konfigurierte
Fallback-Anmeldung gemäß `AuthentificationKind` jedoch greifen.
Tracelinks: SyRS-01, SyRS-02, SyRS-04, SwRS-12, SwRS-13
Konsolidierung: nein
Status: belegt
```
## StRS-25
```
ID: StRS-25
Titel: Deutschsprachige Bedienung mit optionaler englischer Oberfläche
Ebene: StRS
Typ: nicht-funktional (Benutzbarkeit)
Akteur: Endanwender
Vorbedingung: —
Fakt: Alle serverseitigen Fehlermeldungen der Geschäftslogik sind in deutscher Sprache formuliert
(z. B. "Der Belegstatus ist ein Pflichtfeld, und muss deswegen gefüllt sein."). Lokalisierte Texte
liegen als `LocalizedStrings.resx` (Deutsch, Basis) und `LocalizedStrings.en.resx` (Englisch) vor;
`CentronNexus` führt `SharedResource.resx` und `SharedResource.en-US.resx`.
Aussage: Das System soll Deutsch als Standardsprache der Oberfläche und der Meldungen verwenden und
zusätzlich Englisch unterstützen, weil es für den deutschsprachigen Markt entwickelt wird.
Ergebnis: Alle anwendersichtbaren Texte erscheinen in Deutsch; bei englischer Spracheinstellung greifen die
englischen Ressourcen.
Belege:
- [PRIMÄR] src/nexus/CentronNexus/SharedResource.resx und SharedResource.en-US.resx — Begründung: Zwei gepflegte Sprachressourcen im Produktivcode.
- [PRIMÄR] src/backend/Centron.BL/Resources/LocalizedStrings (Verwendung z. B. in Authenticator.cs: `LocalizedStrings.UsersBL_AuthenticateAppUser_MitarbeiterKontoWurdeDeaktiviert`) — Begründung: Meldungen werden über Ressourcen lokalisiert, nicht hart kodiert.
- [KONTEXT] docs/getting-started/general-structure.md, Abschnitt "German-First Language Policy" — "All UI labels must be written in German … The application supports both German (default) and English through separate resource files" — Begründung: Explizite Herstellervorgabe.
- [KONTEXT] docs/guides/ui/localization.md — Begründung: Eigener Leitfaden zur Lokalisierung.
Prüfidee: Anwendung mit englischer Kultur starten; alle in `LocalizedStrings.en.resx` gepflegten Texte müssen
englisch erscheinen, ohne dass deutsche Restbestände in denselben Dialogen auftreten.
Tracelinks: SyRS-38, SwRS-29
Konsolidierung: Kandidat: Es existieren mindestens zwei getrennte Ressourcenkataloge (WPF-Client und Nexus) mit
teils identischen Begriffen; im Zielsystem zu einem Terminologiebestand zusammenzuführen.
Status: belegt
```
## StRS-26
```
ID: StRS-26
Titel: RMA- und Werkstattabwicklung
Ebene: StRS
Typ: funktional
Akteur: Servicetechniker / Werkstattleitung
Vorbedingung: Ein Gerät oder Artikel wird zur Reparatur/Rücksendung angenommen.
Fakt: `RmaBL` vergibt Nummern aus den Nummernkreisen `RepairEntrance`, `RMANumber` und `Reshipment`;
`RMAState` kennt u. a. den Zustand `Canceled`. `ReceiptProgressionBL.CreateRmaReceiptSql` /
`CreateRMASpecificSql` verknüpfen RMA-Vorgänge mit Belegen. Das Modul `RmaOverviewAppModulController`
ist an das Recht `RIGHT_RMAANLEGEN` und die Lizenzen `RMAWorkshop`/`RmaBeta` gebunden.
Aussage: Das System soll Reparatur- und Rücksendevorgänge mit eigenem Nummernkreis, Statusverlauf und
Belegbezug führen, damit Gewährleistungs- und Werkstattfälle abwickelbar und abrechenbar sind.
Ergebnis: Zu jedem RMA-Vorgang sind Eingang, Bearbeitungsstatus und Rückversand nachvollziehbar; zugehörige
Belege sind über die Belegprogression auffindbar.
Belege:
- [PRIMÄR] src/backend/Centron.BL/CustomerArea/RmaBL.cs, Z. 1109/1263/1277 — `GetNextNumber(NumberGroupEnum.RepairEntrance…)`, `…RMANumber…`, `…Reshipment…` — Begründung: Eigenständige, durchgesetzte Nummernkreise je RMA-Teilprozess.
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs, `CreateRmaReceiptSql` / `CreateRMASpecificSql` — Begründung: RMA ist in die Belegverkettung integriert.
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskHistoryBL.cs, Z. 166 — `"RMA " + rmaArticleHistory.RmaArticleState.GetDescription() + ((rmaArticleHistory.State == RMAState.Canceled) ? …)` — Begründung: RMA-Statuswechsel werden in der Tickethistorie sichtbar; Verzahnung mit dem Serviceprozess.
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Modules/ModuleRegistration.cs — Modul "RMA/Werkstatt" mit Recht `RIGHT_RMAANLEGEN` — Begründung: Anwenderseitige Prozessunterstützung.
Prüfidee: RMA-Vorgang anlegen: Es müssen drei getrennte Nummern (Reparatureingang, RMA, Rückversand) aus den
jeweiligen Nummernkreisen vergeben und im Vorgang gespeichert werden.
Tracelinks: SyRS-13, SyRS-15, SwRS-14
Konsolidierung: nein
Status: belegt; Workaround — `HelpdeskCloseBL.CanCloseHelpdesk` enthält den offenen Hinweis
`//Todo: if rma exists check if finished` und gibt derzeit unbedingt `true` zurück; die fachlich
erwartete Kopplung "Ticket erst schließbar, wenn RMA abgeschlossen" ist nicht implementiert.
```
---
## Übersicht StRS
| ID | Titel | Typ | Status |
|---|---|---|---|
| StRS-01 | Mandanten- und Filialstruktur | funktional | belegt |
| StRS-02 | Rollen- und rechtebasierter Zugriff | Sicherheit | belegt |
| StRS-03 | Lizenzabhängiger Funktionsumfang | funktional | belegt |
| StRS-04 | Durchgängige Belegkette | funktional | belegt |
| StRS-05 | Belegabschluss und Storno | funktional | belegt |
| StRS-06 | Vertragsbasierte wiederkehrende Abrechnung | funktional | belegt |
| StRS-07 | Kontingentverwaltung in Verträgen | funktional | belegt |
| StRS-08 | Serviceticket-Bearbeitung (Helpdesk) | funktional | belegt |
| StRS-09 | Zeiterfassung mit Abrechnungsbezug | funktional | belegt |
| StRS-10 | Mehrere Abrechnungsverfahren | funktional | belegt |
| StRS-11 | Kundenportal zur Selbstbedienung | funktional | belegt |
| StRS-12 | Warenkorb mit Freigabeprozess | funktional | belegt |
| StRS-13 | Elektronische Rechnung (ZUGFeRD/XRechnung) | Schnittstelle | belegt |
| StRS-14 | Buchhaltungsübergabe | Schnittstelle | belegt |
| StRS-15 | Mahnwesen und offene Posten | funktional | belegt |
| StRS-16 | Artikel-, Lager- und Bestandsverwaltung | funktional | belegt |
| StRS-17 | Einkaufsprozess mit Lieferantenbelegen | funktional | belegt |
| StRS-18 | Provisionsermittlung | funktional | belegt |
| StRS-19 | Controlling und Auswertungen | funktional | belegt |
| StRS-20 | DSGVO-Betroffenenrechte | Sicherheit | belegt |
| StRS-21 | Nachvollziehbarkeit fachlicher Änderungen | nicht-funktional | belegt |
| StRS-22 | Digitale Freigabe/Unterzeichnung (C-Sign) | funktional | belegt |
| StRS-23 | Anbindung externer Systeme | Schnittstelle | belegt |
| StRS-24 | Zentrale Authentifizierung, SSO, 2FA | Sicherheit | belegt |
| StRS-25 | Deutschsprachige Bedienung, optional Englisch | nicht-funktional | belegt |
| StRS-26 | RMA- und Werkstattabwicklung | funktional | belegt; Workaround |
@@ -0,0 +1,176 @@
# Traceability-Matrix
**System:** NEXOWARE c-entron ERP-Suite
**Norm:** ISO/IEC/IEEE 29148:2018 (Forward- und Backward-Traceability zwischen StRS, SyRS und SwRS)
**Erstellt:** 2026-08-25
Die Matrix ist in beide Richtungen lesbar: Von der Stakeholder-Anforderung abwärts zur Realisierung
(Forward) und von einer Softwareanforderung aufwärts zur Geschäftsbegründung (Backward). Die Spalte
`Artefaktbeleg` nennt jeweils den führenden `PRIMÄR`-Beleg der Kette; die vollständige Belegliste steht in
den drei Spezifikationsdokumenten.
---
## 1. Konsolidierte Matrix StRS → SyRS → SwRS
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (führend) |
|---|---|---|---|
| StRS-01 Mandanten-/Filialstruktur | SyRS-14 Filialspezifische Nummernkreise | SwRS-14 Nummernkreisbaustein | `src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs` → `DoBeforeStoreTrans`: `GetNumberGroup(NumberGroupEnum.Helpdesk, branch: entity.Branch)` |
| StRS-01 | SyRS-21 Filialbeschränkung Belege | SwRS-15 Zentrale Belegprüfmethoden | `Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CanUserCreateReceiptsInBranch<TReceipt>` |
| StRS-02 Rechtebasierter Zugriff | SyRS-09 Modulsichtbarkeit Rechte ∧ Lizenz | SwRS-30 Deklarative Modulregistrierung | `Centron.WPF.UI/Modules/ModuleRegistration.cs` → `DoRegisterCentronModules` |
| StRS-02 | SyRS-09 | SwRS-31 Ausdrucksbaumparser | `Centron.WPF.UI/Modules/ModuleRightsExpressionParser.cs` |
| StRS-02 | SyRS-10 Restriktive Rechte | SwRS-09 Zentraler Rechtekatalog | `…/Rights/UserRightsConst.cs`; `Centron.BL/Sales/Support/HelpdeskBL.cs` Z. 271–290 |
| StRS-02 | SyRS-20 Belegartspezifische Rechteprüfung | SwRS-15 | `Centron.BL/Sales/Receipts/ReceiptBL.cs` Z. 10203–10310 |
| StRS-03 Lizenzabhängiger Funktionsumfang | SyRS-07 Lizenzprüfung/Nutzungszählung | SwRS-11 Lizenz-/Anwendungskatalog | `Centron.BL/Administration/Licensing/LicenseManager.cs` → `CheckLicense` |
| StRS-03 | SyRS-08 Anwendungsspezifische Zugangsrechte | SwRS-11 | `Centron.Interfaces/Administration/Logins/ApplicationKind.cs` |
| StRS-03 | SyRS-09 | SwRS-30 | `ModuleRegistration.cs` → `CheckModuleFeatures()` |
| StRS-04 Belegkette | SyRS-11 Objektartenkodierung | SwRS-06 Primärschlüssel `I3D` | `Centron.Interfaces/CentronObjectKindNumeric.cs` |
| StRS-04 | SyRS-15 Belegweiterführung | SwRS-17 Belegprogression über SQL | `Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs` → `CreateOriginReceiptsSql` |
| StRS-04 | SyRS-16 Anzahlungsrechnung | SwRS-17 | `ReceiptProgressionBL.cs` → `CreateDownPaymentSql` (`RechKopf.DownPaymentForOrderI3D`) |
| StRS-04 | SyRS-17 Belegversionierung | SwRS-16 Abstrakte Belegbasisklasse | `Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CreateNewVersion<T>` |
| StRS-04 | SyRS-18 Optimistische Nebenläufigkeit | SwRS-16 | `Centron.Entities/…/ReceiptBase.cs` → `ConcurrencyControlGuid` |
| StRS-04 | SyRS-19 Pessimistische Belegsperre | SwRS-16 | `Centron.BL/Sales/Receipts/ReceiptBL.cs` → `CreateLock<T>` / `RemoveLock<T>` |
| StRS-04 | SyRS-23 Konfigurierbare Pflichtfelder | SwRS-08 Einstellungsverwaltung | `Centron.BL/Sales/Receipts/Invoices/InvoiceSpecificLogic.cs` Z. 750–752 |
| StRS-04 | SyRS-25 Belegausgabe über Reportgruppen | SwRS-22 ZUGFeRD-Implementierung | `ReceiptBL.cs` → `CreateFullReportForReceipt` (Z. 3221) |
| StRS-05 Belegabschluss/Storno | SyRS-12 Belegzustände | SwRS-16 | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
| StRS-06 Vertragsabrechnung | SyRS-32 Intervall-/Kontingentabrechnung | SwRS-21 Vertragsabrechnungsbausteine | `AutomaticFacturaBL.Contracts.cs` Z. 1101–1234 |
| StRS-06 | SyRS-33 Vor-/nachschüssig | SwRS-21 | `Centron.Interfaces/Sales/BillingCenter/Contracts/BillingKind.cs` |
| StRS-07 Kontingentverwaltung | SyRS-32 | SwRS-21 | `…/Contracts/ContingentKinds.cs`, `DifferContingentInterval.cs` |
| StRS-08 Helpdesk | SyRS-27 Konfigurierbare Ticketstatus | SwRS-19 Ticketmodell | `Centron.DAO/Mappings/CustomerArea/Support/HelpdeskStateBaseMaps.cs` (`hlpdsk_status`) |
| StRS-08 | SyRS-28 Rechtegeprüfter Abschluss | SwRS-19 | `Centron.BL/Sales/Support/HelpdeskCloseBL.cs` → `CloseHelpdesk` |
| StRS-08 | SyRS-29 Historisierung | SwRS-19 | `Centron.BL/Sales/Support/HelpdeskBL.cs` → `SetHelpdeskAction` |
| StRS-08 | SyRS-30 Eskalationsrücksetzung | SwRS-19 | `HelpdeskBL.cs` → `helpdesk.EscalationLevel = 0;` |
| StRS-09 Zeiterfassung | SyRS-31 Schutz abgerechneter Zeiten | SwRS-20 Zeiterfassungsentität | `Centron.BL/Sales/Support/HelpdeskTimerBL.cs` Z. 564–565 |
| StRS-10 Abrechnungsverfahren | SyRS-32 | SwRS-21 | `ModuleRegistration.cs`, Region "Abrechnung" (5 Module) |
| StRS-10 | SyRS-33 | SwRS-21 | `ReceiptBL.cs` → `CreateNewReceiptForHelpdekTimers` (Z. 5295) |
| StRS-11 Kundenportal | SyRS-01 Anmeldung | SwRS-10 Web-Account-Rechtekatalog | `AuthenticatorFactory.cs` → `WebLoginType.Customer` → `WebAccountAuthenticator` |
| StRS-11 | SyRS-20 | SwRS-10 | `HelpdeskBL.cs` → `CheckWebRights` |
| StRS-11 | SyRS-35 Trennung Mitarbeiter/Kunde | SwRS-24 Portal-Autorisierungsrichtlinien | `CentronNexus/Shared/Authorization/CentronAuthorization.cs` |
| StRS-11 | SyRS-36 Uploadbegrenzung | SwRS-24 | `CentronNexus/Configuration/UploadConfig.cs`; `appsettings.json` |
| StRS-12 Warenkorbfreigabe | SyRS-34 Freigabeprozess | SwRS-18 Zustandsmaschine | `ReceiptCartReleaseSystemBL.cs` → `UpdateReceiptCartState` |
| StRS-13 E-Rechnung | SyRS-26 E-Rechnung/Buchhaltungsexport | SwRS-22 | `ReceiptBL.cs` → `GetLeitwegID`, `GetLocalZUGFeRDSetting` |
| StRS-14 Buchhaltungsübergabe | SyRS-26 | SwRS-22 | `Centron.BL/DataExchange/BookKeeping/BookKeepingExportBL.cs` → `IsReceiptExported` |
| StRS-15 Mahnwesen/OPOS | SyRS-22 Mahnstufensperre | SwRS-15 | `ReceiptBL.cs` Z. 10214–10218 |
| StRS-16 Artikel/Lager | SyRS-11 | SwRS-05 NHibernate-Mapping | `Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs` |
| StRS-17 Einkauf | SyRS-11 | SwRS-17 | `Centron.Entities/…/Receipts/SupplierInvoices/`, `SupplierOrders/` |
| StRS-17 | SyRS-20 | SwRS-15 | `ReceiptBL.cs` → `ExternalReceiptNumberAlreadyExists` (Z. 5082) |
| StRS-18 Provision | SyRS-20 | SwRS-15 | `InvoiceSpecificLogic.cs` Z. 469–517 (`InvoiceAutoProvision*`) |
| StRS-19 Controlling | SyRS-10 | SwRS-09 | `Centron.BL/Statistics/ContractStatistics/ContractEvaluationBL.cs` |
| StRS-20 DSGVO | SyRS-45 DSGVO-Löschen | SwRS-07 Löschkennzeichen | `Centron.BL/Administration/DataSecurity/DataSecurityBL.cs` Z. 26–27, 787–851 |
| StRS-21 Nachvollziehbarkeit | SyRS-29 | SwRS-19 | `HelpdeskBL.cs` → `SetHelpdeskAction` |
| StRS-21 | SyRS-37 Änderungsprotokoll | SwRS-07 | `Centron.DAO/Mappings/ChangeTracking/ChangeLogMaps.cs` |
| StRS-22 Digitale Signatur | SyRS-46 Web-Beleg-Freigabestatus | SwRS-24 | `Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs`; `ReceiptBL.cs` Z. 7041–7052 |
| StRS-23 Externe Systeme | SyRS-47 Konnektorkonfiguration | SwRS-27 Integrationsassemblies | `src/apis/` (8 Projekte); `ApplicationSettingDefinitions.cs` (`ITscopeApiKey`) |
| StRS-24 Authentifizierung | SyRS-01 Anmeldung | SwRS-12 Authenticator-Hierarchie | `BasicAuthenticator.cs` → `AuthenticateInternal` |
| StRS-24 | SyRS-02 Verfahrenswahl/Fallback | SwRS-12 | `AuthenticatorFactory.cs` → `GetAuthenticatorWithSystemAuth` |
| StRS-24 | SyRS-03 Kontosperre | SwRS-13 Ticketablage | `Authenticator.cs` → `ValidateAppUser` |
| StRS-24 | SyRS-04 Zweitfaktor | SwRS-12 | `BasicAuthenticator.cs` → `_twoFactorAuthBL.ValidateTwoFactor(...)` |
| StRS-24 | SyRS-05 Ticketsitzung | SwRS-13 | `TicketBL.cs` → `GetExpireDate` (Z. 136–163) |
| StRS-24 | SyRS-06 Verzögerte Ticketverlängerung | SwRS-13 | `TicketBL.cs` → `RefreshTicketExpireDate` |
| StRS-24 | SyRS-44 Passwortspeicherung | SwRS-13 | `Centron.BL/Core/CryptoUtils.cs` → `CreatePasswordHash` (SHA-1) |
| StRS-25 Sprache | SyRS-38 Sprachumschaltung | SwRS-29 ResX-Lokalisierung | `CentronNexus/SharedResource.resx` / `SharedResource.en-US.resx` |
| StRS-26 RMA/Werkstatt | SyRS-13 Nummernvergabe | SwRS-14 | `Centron.BL/CustomerArea/RmaBL.cs` Z. 1109/1263/1277 |
| StRS-26 | SyRS-15 | SwRS-17 | `ReceiptProgressionBL.cs` → `CreateRmaReceiptSql` |
---
## 2. Querschnitts- und Betriebsanforderungen (SyRS ohne direkte StRS-Fachfunktion)
Diese SyRS-Anforderungen realisieren keine einzelne Fachfunktion, sondern tragen mehrere Stakeholder-Ziele
gemeinsam. Sie sind hier separat geführt, damit die Hauptmatrix eindeutig bleibt.
| SyRS-ID | Getragene StRS-Ziele | SwRS-ID | Artefaktbeleg (führend) |
|---|---|---|---|
| SyRS-13 Nummernvergabe mit Kollisionsschutz | StRS-04, StRS-08, StRS-26 | SwRS-14 | `NumberGroupBL.cs` → `GetNextNumber` (bedingtes Update, `rowCountChanged == 1`) |
| SyRS-24 Steuerliche Identifikationspflicht | StRS-04, StRS-13 | SwRS-15 | `ReceiptBL.cs` → `CheckRevenueIdentificationNumberOrTaxNumber` |
| SyRS-39 Automatische Datenbankmigration | StRS-02 (Betriebsfähigkeit über Versionen) | SwRS-23 | `Centron.BL/Administration/Scripts/ScriptEngineBL.cs` + 764 `ScriptMethod*.cs` |
| SyRS-40 Hintergrunddienst Datenqualität | StRS-21 | SwRS-26 | `docs/Background Service/DataQualityService.md`; `Centron.BL/Administration/BackgroundServices/` |
| SyRS-41 Protokollierung | StRS-21 | SwRS-26 | `Centron.WPF.UI/nlog.config`; `CentronNexus.Host/appsettings.json` |
| SyRS-42 Linux-Containerbetrieb | StRS-11, StRS-25 | SwRS-28 | `docker/Dockerfile` |
| SyRS-43 Automatisierte Qualitäts-/Sicherheitsprüfung | StRS-02 | SwRS-33 | `azure/analyze-pipeline.yml` (CodeQL, Dependency Scanning) |
---
## 3. Rückwärtsverfolgung: SwRS → SyRS → StRS
| SwRS-ID | SyRS-ID(s) | StRS-ID(s) |
|---|---|---|
| SwRS-01 Schichtenarchitektur | SyRS-11 | StRS-04, StRS-16, StRS-17 |
| SwRS-02 Duale Datenzugriffsimplementierung | SyRS-09 | StRS-02, StRS-03 |
| SwRS-03 `Result`-Ergebnisobjekt | SyRS-20, SyRS-23 | StRS-02, StRS-04 |
| SwRS-04 Strategiemuster Belegartlogik | SyRS-20, SyRS-23 | StRS-02, StRS-04 |
| SwRS-05 NHibernate-Mapping | SyRS-11, SyRS-37 | StRS-16, StRS-21 |
| SwRS-06 Primärschlüssel `I3D` | SyRS-11 | StRS-04 |
| SwRS-07 Nachverfolgungs-/Löschkennzeichen | SyRS-37, SyRS-45 | StRS-20, StRS-21 |
| SwRS-08 Einstellungsverwaltung | SyRS-23 | StRS-04 |
| SwRS-09 Rechtekatalog | SyRS-10, SyRS-20 | StRS-02, StRS-19 |
| SwRS-10 Web-Account-Rechtekatalog | SyRS-20, SyRS-34, SyRS-35 | StRS-11, StRS-12 |
| SwRS-11 Lizenz-/Anwendungskatalog | SyRS-07, SyRS-08 | StRS-03 |
| SwRS-12 Authenticator-Hierarchie | SyRS-01, SyRS-02, SyRS-04 | StRS-24 |
| SwRS-13 Ticketablage/Schlüsselableitung | SyRS-05, SyRS-44 | StRS-24 |
| SwRS-14 Nummernkreisbaustein | SyRS-13, SyRS-14 | StRS-01, StRS-04, StRS-26 |
| SwRS-15 Zentrale Belegprüfmethoden | SyRS-20, SyRS-21, SyRS-22, SyRS-23, SyRS-24 | StRS-02, StRS-15, StRS-17, StRS-18 |
| SwRS-16 Abstrakte Belegbasisklasse | SyRS-12, SyRS-17, SyRS-18, SyRS-19 | StRS-04, StRS-05 |
| SwRS-17 Belegprogression über SQL | SyRS-11, SyRS-15, SyRS-16 | StRS-04, StRS-17, StRS-26 |
| SwRS-18 Zustandsmaschine Warenkorbfreigabe | SyRS-34 | StRS-12 |
| SwRS-19 Ticketmodell | SyRS-27, SyRS-28, SyRS-29, SyRS-30 | StRS-08, StRS-21 |
| SwRS-20 Zeiterfassungsentität | SyRS-31 | StRS-09 |
| SwRS-21 Vertragsabrechnungsbausteine | SyRS-32, SyRS-33 | StRS-06, StRS-07, StRS-10 |
| SwRS-22 ZUGFeRD-Implementierung | SyRS-25, SyRS-26 | StRS-13, StRS-14 |
| SwRS-23 Migrationsskripte | SyRS-39 | StRS-02 |
| SwRS-24 Portal-Autorisierungsrichtlinien | SyRS-35, SyRS-36, SyRS-46 | StRS-11, StRS-22 |
| SwRS-25 Zwei REST-Generationen | SyRS-05, SyRS-08 | StRS-24 |
| SwRS-26 NLog-Protokollierung | SyRS-40, SyRS-41 | StRS-21 |
| SwRS-27 Integrationsassemblies | SyRS-26, SyRS-47 | StRS-23 |
| SwRS-28 Plattform-/Frameworkbasis | SyRS-42, SyRS-43 | StRS-11, StRS-25 |
| SwRS-29 ResX-Lokalisierung | SyRS-38 | StRS-25 |
| SwRS-30 Deklarative Modulregistrierung | SyRS-09 | StRS-02, StRS-03 |
| SwRS-31 Ausdrucksbaumparser | SyRS-09 | StRS-02 |
| SwRS-32 DTO-Mapperprofile | SyRS-11 | StRS-04 |
| SwRS-33 Testarchitektur | SyRS-43 | StRS-02 |
| SwRS-34 Entwicklerschutz (HYPOTHESE) | SyRS-28, SyRS-43 | StRS-08 |
| SwRS-35 Quelldateikodierung | SyRS-38 | StRS-25 |
| SwRS-36 Benannte Abfragen/Rohzugriff | SyRS-13, SyRS-15 | StRS-04 |
---
## 4. Abdeckungsübersicht
| Kennzahl | Wert |
|---|---|
| StRS-Anforderungen gesamt | 26 |
| SyRS-Anforderungen gesamt | 47 |
| SwRS-Anforderungen gesamt | 36 |
| **Summe Anforderungen** | **109** |
| StRS ohne SyRS-Nachfolger | 0 |
| SyRS ohne StRS-Vorgänger | 0 (7 davon über die Querschnittsmatrix in Abschnitt 2 zugeordnet) |
| SyRS ohne SwRS-Nachfolger | 0 |
| SwRS ohne SyRS-Vorgänger | 0 |
| Anforderungen ohne mindestens einen Beleg | 0 |
| Anforderungen ohne mindestens einen `PRIMÄR`-Beleg | 1 (SwRS-34, deshalb als `HYPOTHESE` geführt) |
| Anforderungen mit Status `HYPOTHESE` | 1 (SwRS-34) |
| Anforderungen mit Status `belegt; Workaround` | 25 |
---
## 5. Konsolidierungskandidaten (Querverweis)
Die folgenden Gruppen bilden dieselbe fachliche Funktion mehrfach ab und sind für die Neuimplementierung
vorrangige Zusammenführungskandidaten. Die Einzelbegründungen stehen im Feld `Konsolidierung` der jeweiligen
Anforderung.
| Nr. | Gruppe | Betroffene IDs | Kern der Redundanz |
|---|---|---|---|
| K-1 | Abrechnungsverfahren | StRS-06, StRS-09, StRS-10; SyRS-32, SyRS-33 | Fünf Module erzeugen jeweils eigenständig Rechnungspositionen aus unterschiedlichen Mengenquellen. |
| K-2 | Historisierung / Audit | StRS-21; SyRS-29, SyRS-37 | Vier parallele Mechanismen: `ChangeLog`, `ReceiptLog`, `ReceiptHistoryEntry`, Helpdesk-Historie. |
| K-3 | Rechtemodelle | StRS-02, StRS-11; SwRS-09, SwRS-10 | Zwei getrennte Kataloge (`UserRightsConst`, `WebAccountRightsConst`) mit überlappender Semantik. |
| K-4 | Organisationsbeschränkung | SyRS-10, SyRS-21 | Filialbeschränkung ist in Helpdesk, Belegwesen und Auswertungen je eigenständig implementiert. |
| K-5 | Einstellungsverwaltung | SwRS-08 | Zwei Tabellen (`Stammdat` / `ApplicationSettings`) mit zwei Enum-Katalogen. |
| K-6 | REST-Schnittstelle | SwRS-25 | 1279 flache POST-Methoden neben versionierten v1-Controllern, teils dieselbe Fachfunktion. |
| K-7 | Nebenläufigkeitskontrolle | SyRS-18, SyRS-19 | Optimistische Kennung und pessimistische Sperre bestehen parallel ohne definierte Vorrangregel. |
| K-8 | Kunden- vs. Lieferantenbelege | StRS-04, StRS-17 | Gemeinsame Basisklasse `ReceiptBase`, aber getrennte Modul-, Einstellungs- und Logikbäume. |
| K-9 | Lokalisierungsbestände | StRS-25; SyRS-38; SwRS-29 | Getrennte Ressourcenkataloge in Backend, WPF-Client und Nexus. |
| K-10 | Datenzugriffswege | SwRS-36 | Vier parallele Wege: LINQ, generische DAO, benannte Abfragen, typisierter Rohzugriff. |
| K-11 | Protokollierungsframeworks | SwRS-26; SyRS-41 | NLog (Backend/WPF) und `Microsoft.Extensions.Logging` (Controller); zwei Konfigurationen mit abweichenden Stufen. |
| K-12 | Konnektorverortung | SwRS-27 | Konnektoren teils unter `src/apis/`, teils in `Centron.BL/DataExchange`. |
| K-13 | Aktiv-/Inaktivkennzeichnung | SwRS-07 | `DBEntity.State` (int, implizit `1` = aktiv) neben `IsDeleted` (bit). |
@@ -0,0 +1,214 @@
# Messprotokoll – V1-Opus (Baseline solo, `claude-opus-5`) – Iteration 01, Lauf 21 (Lauf O)
> **Neue Messreihe.** Erster Block mit `claude-opus-5`; alle 16 Vorläufe nutzten
> `claude-sonnet-5`. Modus, Effort, Prompt, Snapshot und Parallelitätsgrad sind identisch zur
> Sonnet-Solo-Reihe – **es wechselt ausschließlich das Modell**. Damit ist der Block als
> Modellvergleich auswertbar, aber **nicht** mit der Sonnet-Reihe zu einer Reihe zu verrechnen.
>
> **Parallelbetrieb:** fünf gleichzeitige Läufe (K–O). **Wanduhrzeit, `duration_ms` und
> `duration_api_ms` sind verzerrt** und nicht mit seriellen Läufen vergleichbar. Tokenverbrauch,
> Anforderungsanzahl und Denials sind unverzerrt.
## Lauf
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
(identisch zu allen bisherigen Läufen)
- **Startzeit:** 2026-08-25T20:00:18+02:00
- **Endzeit:** 2026-08-25T20:43:25+02:00
- **Dauer gesamt:** 00:43:07 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:43:05 (`duration_ms`) — API: 00:40:41
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Prüfung: 0 Treffer);
Remote entkoppelt: **ja**
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
## Werkzeugkonfiguration
- **Laufverzeichnis-ID:** `v3.6.0-f63e`
- **Ablage:** `claude-opus-5/solo/high/`
- **Parallele Läufe:** ja – die vier übrigen Läufe dieses Blocks (`opus5_solo_v3.6.0-2603`, `opus5_solo_v3.6.0-6bfe`, `opus5_solo_v3.6.0-5070`, `opus5_solo_v3.6.0-26d8`)
- **Skill-Version:** `3.6.0`
- **Claude-Code-Version:** 2.1.245
- **CLI-Pfad:** `C:\Users\ChristophSchwoerer\.vscode\extensions\anthropic.claude-code-2.1.245-win32-x64\resources\native-binary\claude.exe`
- **Agentenmodus:** `solo` (V1) – erzwungen über `--disallowedTools Task Agent Workflow`
- **Effort:** `high` – **explizit per `--effort` gesetzt**; Gegenprobe im Transkript: 183
Nachrichten, durchgängig `high`
- **Modell:** `claude-opus-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/23 Output-Tokens)
- **Permission-Mode:** `acceptEdits`
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Einträgen
(22 × `Bash(...)`, 11 × `PowerShell(...)`, 3 × Agentenwerkzeuge)
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
zusätzlich `--safe-mode` und `--strict-mcp-config`
- **MCP-Server / Agentendateien:** keine – aus dem Snapshot entfernt, zusätzlich `--safe-mode`
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
- **Verschachtelung:** `spawned` = 0, `spawned_by_subagents` = 0, `max_depth` = 0
- **Fast-Mode:** aus
## Verbrauch
### Hauptagent (`usage`)
| Messgröße | Wert |
|---|---|
| Input-Tokens | 182 |
| Output-Tokens | 214.157 (davon 11.239 Thinking-Tokens) |
| Cache-Write-Tokens | 409.702 |
| Cache-Read-Tokens | 19.123.275 |
| Agent-Turns | 131 |
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
| Messgröße | `claude-opus-5` | `claude-haiku-4-5-20251001` | Summe |
|---|---:|---:|---:|
| Input-Tokens | 182 | 4.192 | 4.374 |
| Output-Tokens | 214.157 | 23 | 214.180 |
| Cache-Write-Tokens | 409.702 | 0 | 409.702 |
| Cache-Read-Tokens | 19.123.275 | 0 | 19.123.275 |
| Tokens gesamt | 19.747.316 | 4.215 | **19.751.531** |
**Tokens gesamt: 19.751.531** — Input + Output + Cache-Write + Cache-Read über alle Modelle.
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-opus-5` identisch.
## Ergebnis
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
- **Session-ID:** `b466da25-9694-4739-a4bf-e8d3815276ca`
- **Permission-Denials:** **0** – —
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** – die Sperre hat gegriffen,
der Lauf ist als V1-Messung gültig
- **Subagenten-Prompts:** entfällt (Modus `solo`)
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
| Datei | Größe | Inhalt |
|---|---:|---|
| `StRS.md` | 68.469 B | 26 Anforderungen |
| `SyRS.md` | 115.213 B | 47 Anforderungen |
| `SwRS.md` | 97.747 B | 36 Anforderungen |
| `Traceability.md` | 15.115 B | 58 Datenzeilen |
| `Hypothesen.md` | 14.077 B | 2 Inline-Markierungen `[HYPOTHESE]` |
| `Glossar.md` | 17.271 B | Domänenbegriffe |
| `Analysebericht.md` | 24.609 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
Summe: **109 Anforderungen** über drei Ebenen.
- **Root unverändert:** ja. `git status --porcelain` vor und nach dem Lauf leer, HEAD `79c1142`.
- **Abschlusstext des Agenten:** siehe `RawResult.json` (`result`)
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 26 | 23,9 % |
| SyRS | 47 | 43,1 % |
| SwRS | 36 | 33,0 % |
| **Gesamt** | **109** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 43 | 39,4 % |
| Sicherheit | 23 | 21,1 % |
| Daten | 12 | 11,0 % |
| Schnittstelle | 8 | 7,3 % |
| Architektur | 7 | 6,4 % |
| Wartbarkeit | 2 | 1,8 % |
| nicht-funktional (Wartbarkeit nach ISO/IEC 25010) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit / Nachweisbarkeit) | 1 | 0,9 % |
| nicht-funktional (Benutzbarkeit) | 1 | 0,9 % |
| nicht-funktional (Performance-Effizienz nach ISO/IEC 25010) | 1 | 0,9 % |
| (9 weitere) | 9 | 8,3 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 394 |
| davon `PRIMÄR` | 277 (70,3 %) |
| davon `SEKUNDÄR` | 52 (13,2 %) |
| davon `KONTEXT` | 65 (16,5 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 108 (99,1 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 99,1 % |
| als `HYPOTHESE` gekennzeichnet | 1 | 0,9 % |
| als Workaround vermerkt | 25 | 22,9 % |
| Konsolidierungskandidaten | 29 | 26,6 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (46 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 109 von 109 mit Tracelinks (100,0 %) |
## Opus-Solo-Block (K–O), fünf Messpunkte
| Messgröße | **Lauf K** | **Lauf L** | **Lauf M** | **Lauf N** | **Lauf O** |
|---|---:|---:|---:|---:|---:|
| Anforderungen | 71 | 119 | 114 | 182 | 109 |
| — StRS / SyRS / SwRS | 15/32/24 | 25/43/51 | 25/49/40 | 42/69/71 | 26/47/36 |
| Tokens gesamt | 13.560.381 | 22.759.401 | 24.860.083 | 24.280.282 | 19.751.531 |
| Output-Tokens | 173.827 | 237.716 | 268.853 | 315.027 | 214.180 |
| Thinking-Tokens | 11.712 | 24.179 | 21.146 | 14.034 | 11.239 |
| Agent-Turns | 116 | 195 | 177 | 145 | 131 |
| Traceability-Zeilen | 49 | 77 | 51 | 88 | 58 |
| Denials / Subagenten | 0 / 0 | 1 / 0 | 1 / 0 | 0 / 0 | 0 / 0 |
**Spannweiten:** Anforderungen 71–182 (Median 114, Faktor 2,6),
Tokens 13.560.381–24.860.083 (Median 22.759.401, Faktor 1,8).
## Modellvergleich: Opus gegen Sonnet, sonst identische Bedingung
| | **Opus-Solo (5 Läufe)** | Sonnet-Solo (5 Läufe) |
|---|---|---|
| Anforderungen | 71 – 182 (Median **114**) | 42 – 82 (Median 67) |
| Tokens gesamt | 13.560.381 – 24.860.083 (Median **22.759.401**) | 4.357.855 – 12.598.503 (Median 5.050.595) |
| Streuung Anforderungen | Faktor 2,6 | Faktor 2,0 |
| Streuung Tokens | Faktor 1,8 | Faktor 2,9 |
| Agent-Turns | 116 – 195 | 67 – 107 |
| Subagenten | 0 (erzwungen) | 0 (erzwungen) |
## Anmerkungen/Auffälligkeiten
1. **Opus liefert deutlich mehr Anforderungen bei deutlich höherem Verbrauch.** Median 114
gegenüber 67 Anforderungen (Faktor 1,7) bei Median 22,76 Mio. gegenüber 5,05 Mio. Tokens
(Faktor 4,5). Der Mehrertrag wird also mit überproportionalem Verbrauch erkauft: Pro
Anforderung wendet Opus rund das 2,7-fache an Tokens auf.
2. **Opus arbeitet kleinschrittiger.** 116 bis 195 Agent-Turns gegenüber 67 bis 107 bei Sonnet –
und das im Einzelkontext ohne Subagenten. Der bisherige Solo-Höchstwert von 107 Turns wird
von jedem einzelnen Opus-Lauf übertroffen.
3. **Die Streuung bleibt im selben Rahmen.** Anforderungen Faktor 2,6 gegenüber 2,0 bei
Sonnet, Tokens Faktor 1,8 gegenüber 2,9. Der Modellwechsel verschiebt das Niveau, nicht
die Stabilität. Die zentrale Aussage der Reihe – dass die Streuung im Solo-Modus klein bleibt
und erst durch selbstgewählte Subagenten explodiert – gilt modellunabhängig.
4. **Zwei folgenlose Denials im Block** (Läufe L und M), beide identisch: `New-Item -ItemType
Directory` auf das **eigene, bereits vorhandene** `Ergebnisse\`-Verzeichnis, geblockt durch
`PowerShell(New-Item:*)`. Beide Läufe lieferten trotzdem alle sieben Artefakte. Die Regel
trifft hier eine idempotente, harmlose Operation im Ausgabeverzeichnis – ein Kandidat für
eine Ausnahme in einer künftigen Skill-Version. Ein Bezug zur Subagenten-Sperre besteht
nicht: `Task`/`Agent`/`Workflow` erzeugten in keinem Solo-Lauf je ein Denial.
5. **Ausreißer nach oben: Lauf N** mit 182 Anforderungen (42/69/71) – mehr als das Doppelte von
Lauf K (71). Der Tokenverbrauch beider Läufe unterscheidet sich dagegen nur um Faktor 1,8.
Die Ausbeute je Token schwankt also stärker als der Verbrauch selbst.
6. **Effort erstmals durchgängig explizit gesetzt** und im Transkript gegengeprüft
(183 Nachrichten, durchgängig `high`). Damit ist die Bedingung nicht mehr nur
rekonstruiert, sondern kontrolliert.
7. **Parallelbetrieb technisch fehlerfrei.** Fünf gleichzeitige Läufe, getrennte Verzeichnisse
mit eigenem `_meta`, keine Kollision, keine Fremddateien, Root unverändert.
8. **Manuelle Eingriffe während des Laufs:** keine.
@@ -0,0 +1 @@
{"is_error":false,"duration_api_ms":2440643,"num_turns":131,"stop_reason":"end_turn","session_id":"b466da25-9694-4739-a4bf-e8d3815276ca","total_cost_usd":19.017799500000006,"usage":{"input_tokens":182,"cache_creation_input_tokens":409702,"cache_read_input_tokens":19123275,"output_tokens":214157,"output_tokens_details":{"thinking_tokens":11239},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":409702,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":1481,"cache_read_input_tokens":429713,"cache_creation_input_tokens":925,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":925},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":23,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004307,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-opus-5":{"inputTokens":182,"outputTokens":214157,"cacheReadInputTokens":19123275,"cacheCreationInputTokens":409702,"webSearchRequests":0,"costUSD":19.0134925,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-opus-5","provider":"firstParty"}},"permission_denials":[],"terminal_reason":"completed","fast_mode_state":"off","fast_mode_disabled_reason":"extra_usage_disabled","subagent_stats":{"spawned":0,"requested":{"background":0,"foreground":0,"unset":0},"started_in_background":0,"max_depth":0,"spawned_by_subagents":0,"completed":0,"failed":0,"killed":{"parent":0,"user":0,"system":0},"refused":{"depth_limit":0,"concurrency_limit":0,"budget":0},"by_type":{}},"subtype":"success","api_error_status":null,"result":"Fertig. Die sieben Ergebnisdateien liegen in `…\\01_Lauf_2026-08-25_195918_opus5_solo_v3.6.0-f63e\\Ergebnisse\\`; die Codebasis wurde nur gelesen (`git status` leer).\n\n## Ergebnis\n\n| Datei | Inhalt |\n|---|---|\n| `StRS.md` | 26 Stakeholder-Anforderungen |\n| `SyRS.md` | 47 Systemanforderungen (NFR nach ISO/IEC 25010 zugeordnet) |\n| `SwRS.md` | 36 Softwareanforderungen |\n| `Traceability.md` | Forward-/Backward-Matrix + 13 Konsolidierungsgruppen |\n| `Hypothesen.md` | 1 markierte Hypothese, 13 offene Fragen, 14 nicht analysierte Bereiche |\n| `Glossar.md` | 45 Domänenbegriffe, 30 Systembegriffe, 7 Begriffsabgrenzungen |\n| `Analysebericht.md` | Modulübersicht, Analysetiefe, Konsistenzcheck, Selbstbewertung |\n\n**Konsistenzcheck (maschinell über alle 109 Blöcke):** keine doppelten IDs, keine Anforderung ohne Beleg, keine toten Tracelinks. 394 Belege, davon 277 `PRIMÄR` (70 %), 52 `SEKUNDÄR`, 65 `KONTEXT`. Status: 83 `belegt`, 25 `belegt; Workaround`, 1 `HYPOTHESE`.\n\n## Analytischer Schwerpunkt\n\nTief analysiert wurden Authentifizierung/Sitzung/Lizenz, Belegwesen, Helpdesk, Zeiterfassung, Vertragsabrechnung, Warenkorb-Freigabe, Rechte-/Lizenzmodell und Betrieb. Erträgreichste Technik war die Suche nach `Result.AsError`-Rückgaben in der Geschäftslogik — die deutschen Fehlermeldungen liefern Regel, Auslöser und Anwendersicht in einem Beleg.\n\nMigrationsrelevante Befunde mit hoher Belegdichte: SHA-1-Passwortspeicherung ohne benutzerindividuelles Salt (`// TODO the password should be salted!!!` im Code, SyRS-44), anmeldefreier tokenbasierter Schreibzugriff auf Web-Belege ohne belegte Ablaufregel (H-02), eine wirkungslose DSGVO-Bereinigungsfunktion (H-06) und 1.279 flache Legacy-REST-Methoden neben versionierten Controllern (SwRS-25).\n\n## Zwei Einschränkungen, die ich hervorheben möchte\n\n**Der Untersuchungsgegenstand ist unvollständig.** Der Code verweist an mindestens vier Stellen auf eine parallel betriebene Delphi-Anwendung, die Teile der Fachlichkeit trägt (Objektartvergabe ab 7600000, Kunden-/Lieferantenanlage bei deaktiviertem `IsAccountManagementActive`, eigene Versionslinie 9.3.x). Dieser Anteil liegt nicht als Datei vor — die Spezifikation kann per Konstruktion nur den .NET-Anteil abdecken (H-11).\n\n**Es gibt keine quantifizierten Performanceanforderungen.** Ich habe keine Schwellenwerte für Antwortzeiten, Nutzerzahlen oder Datenvolumen gefunden. Statt Zahlen zu erfinden, ist die Lücke als H-13 dokumentiert; die einzige belegte quantitative Aussage ist die interne 5-Minuten-Schwelle der Ticketverlängerung.\n\nEine Abdeckungsquote habe ich bewusst nicht angegeben — sie wäre in dieser Werkzeugkonfiguration nicht belegbar. Von rund 70 registrierten Modulen sind etwa 20 fachlich spezifiziert; die übrigen sind nur formal über das Lizenz-/Sichtbarkeitsmodell erfasst.","ttft_ms":3527,"ttft_stream_ms":2783,"time_to_request_ms":40,"type":"result","duration_ms":2584983,"uuid":"909ce131-6626-478d-934c-e6042b599a10","queued_turn_count":0}
@@ -0,0 +1,59 @@
## Gefundene Anforderungen
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
### Verteilung über die Ebenen
| Ebene | Anzahl | Anteil |
|---|---:|---:|
| StRS | 26 | 23,9 % |
| SyRS | 47 | 43,1 % |
| SwRS | 36 | 33,0 % |
| **Gesamt** | **109** | 100 % |
### Anforderungstypen
| Typ | Anzahl | Anteil |
|---|---:|---:|
| funktional | 43 | 39,4 % |
| Sicherheit | 23 | 21,1 % |
| Daten | 12 | 11,0 % |
| Schnittstelle | 8 | 7,3 % |
| Architektur | 7 | 6,4 % |
| Wartbarkeit | 2 | 1,8 % |
| nicht-funktional (Wartbarkeit nach ISO/IEC 25010) | 2 | 1,8 % |
| nicht-funktional (Zuverlässigkeit / Nachweisbarkeit) | 1 | 0,9 % |
| nicht-funktional (Benutzbarkeit) | 1 | 0,9 % |
| nicht-funktional (Performance-Effizienz nach ISO/IEC 25010) | 1 | 0,9 % |
| (9 weitere) | 9 | 8,3 % |
### Belegqualität
| Messgröße | Wert |
|---|---:|
| Belege gesamt | 394 |
| davon `PRIMÄR` | 277 (70,3 %) |
| davon `SEKUNDÄR` | 52 (13,2 %) |
| davon `KONTEXT` | 65 (16,5 %) |
| Belege je Anforderung (Median) | 4 |
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 108 (99,1 %) |
### Status
| Kategorie | Anzahl | Anteil |
|---|---:|---:|
| belegt | 108 | 99,1 % |
| als `HYPOTHESE` gekennzeichnet | 1 | 0,9 % |
| als Workaround vermerkt | 25 | 22,9 % |
| Konsolidierungskandidaten | 29 | 26,6 % |
| mit ISO-25010-Qualitätsmerkmal | 0 | 0,0 % |
### Regelkonformität (Prüfung gegen die Vorgaben des Prompts)
| Vorgabe | Ergebnis |
|---|---|
| **Belegpflicht** – jede Anforderung mindestens ein Artefaktbeleg | **erfüllt** (0 Anforderungen ohne Beleg) |
| **Risikobasierte Priorisierung** – Sicherheit, Abrechnung, Berechtigungen brauchen einen `PRIMÄR`-Beleg oder die Kennzeichnung `[HYPOTHESE]` | **erfüllt** (46 risikorelevante Anforderungen, alle gedeckt) |
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
| **Traceability** – Verknüpfung zwischen den Ebenen | 109 von 109 mit Tracelinks (100,0 %) |
@@ -0,0 +1,132 @@
# Versuch 01 - Baseline (Prompt-only) - Iteration 01
## Metadaten
- **Versuch:** V1 Baseline (Prompt-only)
- **Iteration:** 01 (Initial-Prompt, zu Versuchsbeginn neu formuliert)
- **Werkzeugkonfiguration:** Claude Code, keine Agentendateien, keine MCP-Server
- **Codebasis:** c-entron ERP-Suite (Windows, C#/XAML, MSSQL)
- **Modell:** Claude (Claude Code)
- **Zeitstempel:** 2026-08-25
- **Änderungsgrund:** Initial-Prompt für V1 Baseline (kein Vorgänger). Vor Erstlauf überarbeitet: Abgleich mit Kap. 4 (RRE-Methodenkette, Evaluationsrahmen) und Kap. 2 (Prozesskontrollen); mit der Vorfassung fand kein Lauf statt.
---
## Prompt
Du bist ein Requirements Engineer im Reverse Requirements Engineering eines Legacy-ERP-Systems. Erzeuge aus der vorliegenden Codebasis eine Anforderungsspezifikation nach **ISO/IEC/IEEE 29148:2018**. Arbeite ausschließlich auf den im Arbeitsverzeichnis liegenden Artefakten (Quellcode, Konfiguration, UI-Ressourcen, ggf. DB-Skripte). Es stehen weder spezialisierte Agenten noch MCP-Server zur Verfügung; nutze nur, was als Datei lesbar ist.
### Auftrag
Erzeuge eine konsolidierte Spezifikation auf den drei Ebenen:
1. **StRS** - Stakeholder Requirements Specification (fachliche Sicht, Akteure, Geschäftsziele)
2. **SyRS** - System Requirements Specification (Systemverhalten, Schnittstellen, Performance-, Sicherheitsanforderungen)
3. **SwRS** - Software Requirements Specification (Komponenten, Datenmodelle, Software-interne Regeln)
Ziel ist eine Spezifikation, die als belastbare Basis für eine Web-/SaaS-Neuimplementierung dienen kann.
### Scope (Schritt 1 der RRE-Methodenkette, manuell vorgegeben)
Der Untersuchungsgegenstand ist die **gesamte Codebasis** im Arbeitsverzeichnis. Es gilt bewusst keine Modulbeschränkung: Alle Module, Datenobjekte und Prozesse sind gleichrangig zu erfassen. Priorisiere die Analysetiefe selbstständig, dokumentiere aber im `Analysebericht.md`, welche Bereiche wie tief analysiert wurden.
### Vorgehen (statische Analyse, keine Ausführung)
Bearbeite die Schritte 2-6 der RRE-Methodenkette (Schritt 1 Scope ist oben vorgegeben, Schritt 7 Validierung erfolgt manuell durch Fachexperten):
2. **Artefakterhebung:** Erfasse Quellcode, Konfiguration, UI-Texte, Datenbankschemata, Schnittstellenbeschreibungen sowie Change-Historie und Projektartefakte (Commit-Messages, Tickets, Release Notes, Migrationsnotizen), soweit als Datei lesbar.
3. **Technische Analyse:** Identifiziere Module, Komponenten, Abhängigkeiten, Statusmaschinen, Validierungslogik, Berechtigungsprüfungen.
4. **Semantische Interpretation:** Leite fachliche Aussagen aus technischen Implementierungen ab (z. B. Statusübergänge → Geschäftsregel).
5. **Formalisierung:** Überführe die Aussagen in klare, testbare Anforderungen mit Kontext, Vorbedingung und Ergebnis.
6. **Traceability-Anreicherung:** Verknüpfe jede Anforderung mit konkreten Artefaktbelegen.
### Pflicht-Eigenschaften jeder Anforderung
- **Belegpflicht:** Jede Anforderung **muss** mindestens einen konkreten Artefaktbeleg führen (Dateipfad, Klasse/Methode, SQL-Statement, UI-String, Konfigurationseintrag). Anforderungen ohne Beleg sind unzulässig. Jeder Beleg erhält eine kurze Begründung, warum er die Aussage trägt.
- **Trennung von Fakt und Interpretation:** Die belegte technische Beobachtung (Feld `Fakt`) wird getrennt von der fachlichen Interpretation (Feld `Aussage`) dokumentiert, damit nachvollziehbar bleibt, was im Artefakt steht und was daraus geschlossen wurde.
- **Risikobasierte Priorisierung:** Anforderungen zu Sicherheitsregeln, Abrechnungs-/Fakturierungslogik und Berechtigungen unterliegen strengeren Evidenzanforderungen: Sie benötigen mindestens einen `PRIMÄR`-Beleg, andernfalls sind sie zwingend als `[HYPOTHESE]` zu kennzeichnen.
- **Belegklassifikation:** Kennzeichne jeden Beleg als
- `PRIMÄR` (durchgesetzte Regel im Code oder DB-Constraint),
- `SEKUNDÄR` (UI-Label, Fehlermeldung, Reportlayout, Mappingtabelle, Konfigurationsschalter),
- `KONTEXT` (Kommentar, Commit-Message, Ticketreferenz).
- **Hypothesenmarkierung:** Aussagen, die sich nicht eindeutig aus Artefakten ableiten lassen, kennzeichnest du explizit mit `[HYPOTHESE]` und einer kurzen Begründung, welche Information zur Bestätigung fehlt.
- **Verifizierbarkeit:** Jede Anforderung enthält mindestens eine Prüfidee oder ein Akzeptanzkriterium.
- **Eindeutigkeit:** Vermeide vage Begriffe ("schnell", "benutzerfreundlich"); definiere domänenspezifische Begriffe beim ersten Auftreten.
### Formatvorgabe pro Anforderung
```
ID: <StRS|SyRS|SwRS>-<laufende Nummer>
Titel: <kurzer Titel>
Ebene: <StRS | SyRS | SwRS>
Typ: <funktional | nicht-funktional | Schnittstelle | Daten | Sicherheit | ...>
Akteur: <Rolle / System / Komponente>
Vorbedingung: <Zustand vor Auslösen>
Fakt: <belegte technische Beobachtung, z. B. Statusübergang, Constraint, Prüfung>
Aussage: Das System soll <...>. (fachliche Interpretation als klare Soll-Aussage)
Ergebnis: <erwartetes Ergebnis / Nachbedingung>
Belege:
- [PRIMÄR] <Pfad/Klasse/Methode/SQL/UI-String> - Begründung: <warum trägt der Beleg die Aussage>
- [SEKUNDÄR] <...> - Begründung: <...>
- [KONTEXT] <...> - Begründung: <...>
Prüfidee: <Akzeptanzkriterium oder Testidee>
Tracelinks: <verwandte StRS-/SyRS-/SwRS-IDs>
Konsolidierung: <nein | Kandidat: <IDs oder Stellen, die dieselbe fachliche Funktion abbilden>>
Status: <belegt | HYPOTHESE>
```
### Traceability
Stelle Forward- und Backward-Traceability zwischen den drei Ebenen her:
- Jede SwRS-Anforderung referenziert die zugehörige SyRS-Anforderung.
- Jede SyRS-Anforderung referenziert die zugehörige StRS-Anforderung.
- Erzeuge zusätzlich eine konsolidierte **Traceability-Tabelle** (Markdown oder CSV): `StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg`.
### Nicht-funktionale Anforderungen
- Ordne nicht-funktionale Anforderungen den Qualitätsmerkmalen der **ISO/IEC 25010** zu (z. B. Zuverlässigkeit, Performance-Effizienz, Sicherheit, Wartbarkeit, Übertragbarkeit).
- Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus indirekt sichtbaren Artefakten ab: Konfigurationen, Deployment-Skripte, Logging-Policies, Rechteprüfungen.
### Konsolidierungsbedarf
Die Codebasis enthält fachliche Redundanz: Dieselbe Anforderung kann auf unterschiedlichen Masken oder in unterschiedlichen Modulen mehrfach und teils unterschiedlich implementiert sein. Prüfe daher bei jeder Anforderung, ob andere Anforderungen dieselbe fachliche Funktion abbilden, und vermerke solche Fälle im Feld `Konsolidierung` als Kandidat für eine Zusammenführung im Zielsystem.
### Ergebnisstruktur (im vorgegebenen Ausgabeverzeichnis)
```
Ergebnisse/
StRS.md
SyRS.md
SwRS.md
Traceability.md (oder Traceability.csv)
Hypothesen.md (Sammlung aller mit [HYPOTHESE] markierten Aussagen mit offener Frage)
Glossar.md (Domänenbegriffe, die in den Anforderungen verwendet werden)
Analysebericht.md (Modul-/Komponentenübersicht, abgedeckte Bereiche, bekannte Lücken)
```
Das Ausgabeverzeichnis wird beim Start des Laufs benannt. Die analysierte Codebasis wird ausschließlich gelesen und nicht verändert.
### Randbedingungen
- **Keine Halluzinationen.** Wenn ein Artefakt nicht gelesen oder eine Aussage nicht belegt werden kann, ist das offen zu legen, nicht zu erfinden.
- **Keine Generierung von Code.** Es sollen ausschließlich Spezifikationsartefakte entstehen.
- **Keine Annahme nicht vorhandener Tools.** Stehen für eine Aussage nur indirekte Belege zur Verfügung, ist die Aussage als `[HYPOTHESE]` zu kennzeichnen.
- **Migrationsperspektive berücksichtigen.** Wenn eine Implementierung erkennbar ein historischer Workaround oder Sonderfall ist, vermerke das im Feld `Status` (`belegt; Workaround`), damit es in der späteren Validierung priorisiert geprüft werden kann.
- **Sprache:** Deutsch für Anforderungsaussagen, technische Bezeichner (Klassen, Methoden, Spalten) bleiben in ihrer Originalsprache.
### Abschluss
Führe vor Abgabe einen **Konsistenzcheck über das gesamte Anforderungs-Set** durch und dokumentiere das Ergebnis im `Analysebericht.md`:
- Doppelte oder mehrfach vergebene IDs
- Anforderungen ohne Beleg
- Tracelinks auf nicht existierende IDs
Beende den Lauf mit einer kurzen Selbstbewertung im `Analysebericht.md`:
- Welche Module wurden vollständig analysiert, welche nur stichprobenhaft, welche gar nicht?
- An welchen Stellen war der Beleg dünn (hoher Anteil `SEKUNDÄR`/`KONTEXT` oder `[HYPOTHESE]`)?
- Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
### Ausgabeverzeichnis (überschreibt anderslautende Pfadangaben oben)
Schreibe ALLE zu erzeugenden Ergebnisdateien in das Verzeichnis
`c:\DEV\MasterArbeit\Versuche\Versuch_01\01_Lauf_2026-08-25_195918_opus5_solo_v3.6.0-f63e\Ergebnisse\`.
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
@@ -0,0 +1 @@
2026-08-25T20:43:25.5805965+02:00
@@ -0,0 +1 @@
2026-08-25T20:00:18.8799897+02:00