Lots of runs
This commit is contained in:
+94
@@ -0,0 +1,94 @@
|
||||
# Analysebericht
|
||||
|
||||
Iteration 01 (Initial-Lauf), V1 Baseline (Prompt-only), Werkzeugkonfiguration: Claude Code ohne Agentendateien/MCP-Server. Analysierte Codebasis: `C:\DEV\MasterArbeit\QuellCode\CentronERP` (c-entron ERP-Suite).
|
||||
|
||||
## 1. Umfang der Codebasis (Fakten)
|
||||
|
||||
| Kennzahl | Wert | Quelle |
|
||||
|---|---|---|
|
||||
| `.cs`-Dateien | 16.063 | `find . -name "*.cs"` |
|
||||
| `.xaml`-Dateien | 1.233 | `find . -name "*.xaml"` |
|
||||
| `.csproj`-Dateien | 44 | `find . -name "*.csproj"` |
|
||||
| Top-Level-Ordner unter `Entities/` (`Centron.Entities`) | 86 | `find ... -maxdepth 1 -type d` |
|
||||
| Top-Level-Ordner unter `Centron.BL` | 93 | `find ... -maxdepth 1 -type d` |
|
||||
| Hauptschichten | `src/backend` (BL/DAO/Entities/Interfaces/Common/Gateway), `src/centron` (WPF-Client), `src/nexus` (Blazor-Portal "CentronNexus"), `src/webservice` (REST/Legacy-Webservice), `src/apis` (externe Integrationen), `src/shared` | `docs/getting-started/ai-codebase-navigation.md` |
|
||||
|
||||
Diese Größenordnung übersteigt die vertretbare vollständige Tiefenanalyse innerhalb einer einzelnen Iteration bei weitem. Es wurde daher – wie im Auftrag vorgesehen ("Priorisiere die Analysetiefe selbstständig") – eine bewusste, dokumentierte Auswahl getroffen.
|
||||
|
||||
## 2. Vorgehen dieser Iteration
|
||||
|
||||
1. **Architektur-Orientierung:** Lektüre der im Repository vorhandenen Entwicklerdokumentation (`docs/getting-started/*`, `docs/guides/development/*`, `docs/reference/*`), da diese als KONTEXT-/SEKUNDÄR-Beleg direkten Zugriff auf die vom Entwicklerteam selbst dokumentierten Architekturregeln bietet.
|
||||
2. **Hotspot-Identifikation:** Analyse der Änderungshäufigkeit über `git log --name-only` (letzte 2 Jahre) als Indikator für fachlich/betrieblich relevante, aktiv gepflegte Bereiche.
|
||||
3. **Vertiefte Belegerhebung** in sechs priorisierten Domänen (siehe Abschnitt 3).
|
||||
4. **Formalisierung** der gefundenen Fakten zu StRS/SyRS/SwRS-Anforderungen mit Belegen, Hypothesenkennzeichnung und Traceability.
|
||||
5. **Konsistenzprüfung** über alle erzeugten Anforderungen (Abschnitt 5).
|
||||
|
||||
## 3. Abdeckung nach Bereich (Analysetiefe)
|
||||
|
||||
| Bereich | Tiefe | Begründung / was wurde gelesen |
|
||||
|---|---|---|
|
||||
| **Rechte-/Berechtigungssystem** (`Administration/Rights`, `UserRightsConst.cs`, `CentronRights.md`) | **Tief** | Vollständige Lektüre `AppRightsBL.cs` (relevante Abschnitte), `UserRightsExt.cs` vollständig, `CentronRights.md` vollständig, Entwicklungsleitfäden zu Rechten vollständig. |
|
||||
| **Verkaufsbelege / Sales.Receipts** (Angebot/Auftrag/Lieferschein/Rechnung/Gutschrift) | **Tief** | `ReceiptState.cs` vollständig, `ReceiptProgressionBL.cs` (Kernmethoden `GetRelatedItemsForObject` und alle SQL-Erzeugungsmethoden für Origin/FollowUp/DownPayment/External), `ReceiptLog.cs` vollständig, Entitätsverzeichnis strukturell erfasst. Nicht gelesen: `ReceiptBL.cs` (Hauptklasse, 800+ Zeilen vermutet), Preis-/Rabattlogik (`ReceiptPriceHelperBL.cs`), Provisionslogik. |
|
||||
| **Helpdesk/Ticketing** | **Mittel-Tief** | `HelpdeskBL.cs` Kernausschnitt (Rechteprüfung, Statuswechsel, Speicherpfad `DoBeforeSave`/`CheckRights`/`CheckUserRigths`) gelesen (~200 von 1043 Zeilen). Nicht gelesen: Zeiterfassungs-BL-Klassen (Grund für HYPOTHESE SwRS-008), Checklisten, C-FLOW-Vorlagenlogik, `HelpdeskSettingsBL.cs` selbst. |
|
||||
| **Authentifizierung/Passwörter** | **Mittel** | `UsersBL.cs` (Passwortpfad vollständig), `SHA1Decoder.cs` vollständig. Nicht gelesen: `TwoFactorAuthenticationBL.cs` (nur Existenz festgestellt), `EntraIDUsersBL.cs`/Microsoft-Login (nur Dokumentationstitel gesichtet), Session-/Token-Handling (`AuthenticationTicketBL.cs`). |
|
||||
| **Lager/Bestand (Warehousing.StockManagement)** | **Oberflächlich-Mittel** | `ArticleStockBL.cs` Kernausschnitt (erste ~150 Zeilen: Lesemethoden, `UpdateArticlePurchasePrice`-Signatur und -Delegation). Nicht gelesen: `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` (eigentliche Bewertungsformel), `StorageAreaBL.cs`, `StoragePlaceBL.cs`, Kommissionierung, Inventur. |
|
||||
| **Nummernkreise (NumberGroupBL)** | **Tief** (für die gelesenen Methoden) | `GetNextNumber`, `FindNextNumber` vollständig gelesen inkl. Kollisions-Sonderfall Kundennummern. |
|
||||
| **EDI/Datenaustausch** | **Nur strukturell** | Verzeichnisstruktur je Partner erfasst (Alltron, ALSO, AlsoCH, Komsa, Concerto, EGIS, Opentrans21, Zugferd, SupplierEDI, Import). Kein einzelner Partner-Connector inhaltlich gelesen. `xrechnung.md` vollständig gelesen (sehr kurz, primär externe Links). |
|
||||
| **CentronNexus (Blazor-Web-Portal)** | **Nur strukturell** | Verzeichnisstruktur (ServiceBoard, WebCart, Settings, Shared/Auth) und Änderungshäufigkeit erfasst. Kein Code inhaltlich gelesen. |
|
||||
| **Architektur-/Schichtenmodell (ILogic/BL/WS)** | **Dokumentationsbasiert** | `general-structure.md` und `ai-codebase-navigation.md` vollständig gelesen. `ClassContainer`-Implementierung selbst nicht gelesen (daher SwRS-011 als SEKUNDÄR statt PRIMÄR belegt). |
|
||||
| **Alle übrigen Module** (Finances, Purchasing, Production, Warehousing.ArticleProduction/Commissions, Statistics, TaskManager, Mail, PLM, QM, RMA im Detail, Buchhaltung/BookKeeping, Reporting/ReportEngine, Mobile, MyCentron, Chats, Merchandise, Devices, Tapi, VideoPortal, VoucherManagement, TradePool, SocialMedia u. v. m.) | **Nicht analysiert** | Nur über die Verzeichnisstruktur (`Entities/`, `Centron.BL/`, `Centron.WPF.UI/Modules/`) zur Kenntnis genommen, keine Datei geöffnet. |
|
||||
|
||||
**Zusammenfassung:** Von 93 Top-Level-BL-Modulordnern wurden 5 (Rights, Sales/Receipts, Sales/Support[Helpdesk], Administration/Logins, Warehousing/StockManagement) sowie 1 Querschnittsthema (Administration/Company/NumberGroupBL) inhaltlich mit Code belegt. Das entspricht einer gezielten Tiefenanalyse von ca. 6–7 % der Modulordner, ausgewählt nach Geschäftskritikalität (Sicherheit, Fakturierung) und Änderungshäufigkeit (Git-Historie).
|
||||
|
||||
## 4. Ergebnis-Übersicht
|
||||
|
||||
| Dokument | Anzahl Anforderungen | Davon vollständig `[HYPOTHESE]` | Davon `Status: belegt; Workaround` |
|
||||
|---|---|---|---|
|
||||
| StRS.md | 14 | 0 (1 mit Teil-Hypothese in Konsolidierung/Status-Zusatz) | 0 |
|
||||
| SyRS.md | 15 | 0 (3 mit Teil-Hypothese im Status-Feld) | 1 (SyRS-014, SHA-1-Hashing) |
|
||||
| SwRS.md | 13 | 1 (SwRS-008) | 2 (SwRS-004, SwRS-013) |
|
||||
| **Summe** | **42** | **1** | **3** |
|
||||
|
||||
Alle 42 Anforderungen tragen mindestens einen Beleg (0 Anforderungen ohne Beleg). Alle sicherheits-/abrechnungsrelevanten Anforderungen (Rechte, Passwort, Beleg-Status/-Nummerierung, Ticket-Abschluss) tragen mindestens einen PRIMÄR-Beleg, mit der einzigen Ausnahme SwRS-008 (Zeiterfassungssperre), die deshalb konsequent vollständig als `[HYPOTHESE]` geführt wird, wie in den Randbedingungen gefordert.
|
||||
|
||||
## 5. Konsistenzcheck (durchgeführt)
|
||||
|
||||
- **Doppelte/mehrfach vergebene IDs:** Keine gefunden. Automatisierte Prüfung (`grep` auf alle `ID:`-Zeilen je Dokument, Deduplizierung) ergab je 14/15/13 eindeutige IDs ohne Duplikate.
|
||||
- **Anforderungen ohne Beleg:** Keine gefunden. Jede der 42 Anforderungen enthält mindestens einen Eintrag im Feld `Belege`.
|
||||
- **Tracelinks auf nicht existierende IDs:** Keine gefunden. Automatisierter Abgleich aller im Text vorkommenden `StRS-\d+`/`SyRS-\d+`/`SwRS-\d+`-Erwähnungen (42 eindeutige) gegen alle deklarierten `ID:`-Werte (42 eindeutige) ergab eine Menge von 0 nicht auflösbaren Referenzen (`comm -23` lieferte leere Ausgabe).
|
||||
- **Einschränkung der Prüfung:** Die Prüfung wurde textbasiert (Shell-Tools) durchgeführt, nicht mit einem dedizierten RE-Tool; sie deckt Syntaxkonsistenz ab, nicht die inhaltliche Korrektheit der Tracelinks (diese wurde beim Schreiben jeder Anforderung manuell gesetzt).
|
||||
|
||||
## 6. Bereiche mit dünner Beleglage
|
||||
|
||||
- **StRS-013/SyRS-013 (Sprachpolitik):** Ausschließlich SEKUNDÄR/KONTEXT-Belege (Dokumentation, keine Codeverifikation der Fallback-Logik). Kein PRIMÄR-Beleg, aber auch kein Sicherheits-/Abrechnungsbezug, daher zulässig gemäß Auftragsvorgabe.
|
||||
- **SwRS-008 (Zeiterfassungssperre):** Ausschließlich KONTEXT-Beleg (`CentronRights.md`), obwohl abrechnungsrelevant → korrekt als vollständige `[HYPOTHESE]` geführt, nicht als "belegt" fehlklassifiziert.
|
||||
- **SwRS-011 (ClassContainer-Auto-Registrierung):** Nur SEKUNDÄR (Dokumentation), da die Reflection-Implementierung selbst nicht lokalisiert/gelesen wurde.
|
||||
- **StRS-010/SyRS-010 (EDI-Partnerformate):** PRIMÄR nur für die *Existenz* der Struktur, nicht für inhaltliche Korrektheit der Mappings (explizit als HYPOTHESE im SyRS-010-Statusfeld vermerkt).
|
||||
|
||||
## 7. Selbstbewertung
|
||||
|
||||
**Vollständig analysiert:** Kein Modul wurde im Sinne von "jede Datei gelesen" vollständig analysiert; selbst die am tiefsten untersuchten Bereiche (Rechte, Verkaufsbelege) wurden gezielt anhand weniger Kernklassen erschlossen.
|
||||
|
||||
**Stichprobenhaft analysiert (mit belastbaren Kernbelegen):** Rechte-/Berechtigungssystem, Verkaufsbeleg-Statusmaschine und -Verkettung, Helpdesk-Rechteprüfung, Passwort-Hashing, Nummernkreisvergabe, Lagerbestandsfortschreibung (Kernpfad).
|
||||
|
||||
**Nur strukturell/gar nicht analysiert:** ca. 85+ der 93 Top-Level-BL-Module, darunter vollständig unangetastet: Finances/Payments/OnlineBanking (Zahlungsverkehr), Buchhaltung/DataExchange.BookKeeping, Purchasing (Einkauf/Bestellvorschlag), Production/ArticleProduction, Statistics (alle Auswertungen), Reporting/ReportEngine (PDF-Erzeugung), TaskManager, Mail/Exchange-Integration, Mobile, CentronNexus (Blazor-Portal) inhaltlich, alle Webservice-Controller (`src/webservice/Centron.Controllers`), alle Datenbankskripte/-migrationen (`Administration/Scripts/ScriptMethods`, obwohl als Fundort für Rechtevergabe referenziert), sämtliche Tests (`tests/**`), sämtliche UI-/XAML-Ressourcen inhaltlich (nur Verzeichnisstruktur), Lizenzierungssystem (`docs/reference/security/licensing-system.md` nicht gelesen), Zwei-Faktor-Authentifizierung (Datei nur als existent festgestellt).
|
||||
|
||||
**Erkenntnisse, die einen Nachschlag in einer Folgeiteration nahelegen:**
|
||||
|
||||
1. **Abrechnungsrelevante Lücke schließen:** `HelpdeskTimer*BL`-Klassen lokalisieren und lesen, um SwRS-008 von HYPOTHESE zu "belegt" zu heben (oder zu widerlegen).
|
||||
2. **Bewertungsformel Lagerbestand:** `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` lesen (Kostenrechnungsrelevanz).
|
||||
3. **Zahlungsverkehr/Buchhaltung:** Bisher komplett unanalysiertes, aber laut Verzeichnisstruktur umfangreiches Feld (`Finances/Payments`, `Finances/OnlineBanking`, `DataExchange/BookKeeping`) — hohe Wahrscheinlichkeit weiterer PRIMÄR-belegpflichtiger Anforderungen (Abrechnungslogik).
|
||||
4. **Sicherheitsvertiefung:** Zwei-Faktor-Authentifizierung, Microsoft-/Entra-ID-Login (`anmelden-mit-microsoft-technische-anleitung.md` vorhanden, nicht gelesen), Lizenzierungssystem, Session-/Token-Handling (`AuthenticationTicketBL.cs`) — sicherheitskritisch, bisher nicht untersucht.
|
||||
5. **Webservice-/API-Schnittstellenverzeichnis:** `src/webservice/Centron.Controllers/Controllers/v1/**` als moderne REST-Schnittstelle systematisch erfassen (relevant für SyRS-Schnittstellenanforderungen einer Web-/SaaS-Neuimplementierung).
|
||||
6. **CentronNexus (Blazor-Portal) inhaltlich:** Trotz hoher Änderungsfrequenz (Top-Hotspot laut Git-Historie) bisher nur strukturell erfasst — hohe Priorität, da dies der UI-Kandidat am nächsten an einer künftigen Web-/SaaS-Oberfläche ist.
|
||||
7. **Konsolidierungskandidaten vertiefen:** Die in dieser Iteration identifizierten Konsolidierungskandidaten (z. B. redundante Enum/Switch-Zuordnung in SwRS-006, zwei parallele Rechtemodelle in SwRS-012) sollten systematisch auf weitere Vorkommen im gesamten Code geprüft werden (in dieser Iteration nur punktuell erkannt, nicht codebasisweit gesucht).
|
||||
8. **EDI-Partnerformate inhaltlich:** Mindestens ein Partnerformat (Vorschlag: ALSO oder Komsa, da im Zeitraum aktiv) inhaltlich mit Testdaten nachvollziehen.
|
||||
|
||||
## 8. Verwendete, aber nicht in Anforderungen zitierte Quellen (zur Transparenz)
|
||||
|
||||
- `README.md` (Kontext für WebCart, Referenzierungsregeln Nexus)
|
||||
- `docs/getting-started/documentation-rules.md` (nicht gelesen)
|
||||
- `docs/reference/architecture/{dtos-and-entities,mvvm-in-centron,requests-and-responses,results-and-responses,stanislaus-secret-api-documentation,tapi}.md` (nur Dateinamen erfasst, Inhalte nicht gelesen)
|
||||
- `docs/reference/security/{licensing-system,anmelden-mit-microsoft-technische-anleitung}.md` (nur Dateinamen erfasst)
|
||||
|
||||
Diese Dateien sind ausdrücklich **nicht** als Grundlage für Anforderungen in dieser Iteration verwendet worden, um keine unbelegten Aussagen zu erzeugen; sie werden hier als Kandidaten für die Folgeiteration aufgeführt.
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
# Glossar
|
||||
|
||||
Domänenbegriffe, wie sie in StRS/SyRS/SwRS verwendet werden. Deutsche Fachbegriffe stammen überwiegend aus UI-Strings, Tabellennamen und `UserRightsConst.cs`; englische/technische Bezeichner bleiben im Original.
|
||||
|
||||
| Begriff | Bedeutung im System | Quelle/Beleg |
|
||||
|---|---|---|
|
||||
| **I3D** | Primärschlüssel-Konvention: nahezu jede Entität (Kunde, Beleg, Recht, Benutzer, Artikel, …) trägt eine Spalte/Property `I3D` als eindeutige numerische ID. Historisch gewachsene, projektweite Konvention (kein Fremdschlüsselsuffix wie üblich `Id`). | Durchgängig in `Centron.Entities`, z. B. `AppRight.I3D`, `ReceiptOrder` (`AufKopf.I3D`); `NumberGroupBL.cs:118` (Kollisionsprüfung auf `Kunden.I3D`) |
|
||||
| **Beleg (Receipt)** | Sammelbegriff für die Dokumentenkette im Verkaufsprozess: Angebot (Offer), Auftrag (Order), Lieferschein (DeliveryList), Rechnung (Invoice), Gutschrift (CreditVoucher). Alle erben fachlich vom Konzept `ReceiptTable`. | `src/backend/Centron.Entities/Entities/Sales/Receipts/**`, `ReceiptTable.cs` |
|
||||
| **Belegkopf/-position (Kopf/Pos)** | Kopf-/Positionsstruktur je Belegtyp, z. B. `AufKopf`/`AufPos` (Auftrag), `LiefKopf`/`LiefPos` (Lieferschein), `RechKopf` (Rechnung). Namensmuster in DB-Tabellen. | `ReceiptProgressionBL.cs:120-160` (SQL-Joins auf `AufKopf`, `AufPos`, `LiefKopf`, `LiefPos`, `RechKopf`) |
|
||||
| **Belegstatus (ReceiptState)** | Lebenszyklus-Status eines Belegs: `Active` ("offen"), `Completed` ("abgeschlossen"), `Canceled` ("storniert"). | `Centron.Interfaces/Sales/Receipts/ReceiptState.cs` |
|
||||
| **Fortschreibung (Progression)** | Prozess, einen Beleg in einen Folgebeleg zu überführen (z. B. Auftrag → Lieferschein → Rechnung) bzw. verknüpfte/Ursprungs-Belege zu ermitteln. | `ReceiptProgressionBL.cs` (`GetRelatedItemsForObject`, `CreateOriginReceiptsSql`, `CreateFollowUpReceiptsSql`) |
|
||||
| **Anzahlungsrechnung (Down Payment)** | Rechnung, die vor Fertigstellung eines Auftrags auf diesen ausgestellt wird; referenziert über `DownPaymentForOrderI3D`. | `ReceiptProgressionBL.cs:140-160` |
|
||||
| **Recht (AppRight/Sichrech)** | Einzelne, feingranulare Berechtigung, referenziert über eine numerische `I3D`; in DB-Tabelle `Sichrech` gespeichert, hierarchisch über `OwnerRecht`/`NumChildren` organisiert. | `Sichrech`-Tabelle (`docs/guides/development/add-a-new-right.md`), `AppRightsBL.cs` |
|
||||
| **Rechtegruppe (AppGroup/Sichmemb)** | Gruppe, der Rechte zugewiesen werden und der Benutzer angehören; Zuordnung Benutzer↔Gruppe über `Sichmemb`, Gruppe↔Recht über `Sichtrus`. | `AppRightsBL.CheckRightsFromUser` (SQL auf `Sichtrus`/`Sichmemb`) |
|
||||
| **Einschränkendes Recht (restricting right)** | Sonderform eines Rechts, das den Wirkungsbereich eines übergeordneten Rechts einschränkt (z. B. "nur eigene Filiale", "nur eigene Tickets"), anstatt eine neue Fähigkeit freizuschalten. | `CentronRights.md` (u. a. `SHOW_HELPDESK_ONLY_OWN_BRANCH`); Begriff wörtlich so im Dokument verwendet |
|
||||
| **Filiale (Branch)** | Organisatorische Einheit, der Benutzer, Tickets u. a. zugeordnet sind; Basis mehrerer einschränkender Rechte. | `CentronRights.md`, `HelpdeskBL.cs:284-286` |
|
||||
| **Mandant (Mandatory/Mandant)** | Übergeordnete organisatorische Einheit oberhalb der Filiale, u. a. Grundlage für Nummernkreise. | `NumberGroupBL.CreateNumberGroups(int mandantI3D, int? branchI3D)` |
|
||||
| **Helpdesk/Ticket** | Vorgang im Kundenservice-Modul (Sales.Customer.Helpdesk); besitzt einen konfigurierbaren Status (`HelpdeskState`), Kategorien, Checklisten, Zeiterfassung. | `HelpdeskBL.cs`, `CentronRights.md` |
|
||||
| **Ticket-Status (HelpdeskState)** | Nicht als festes Enum, sondern als konfigurierbarer Stammdatensatz modelliert; welcher Status als "geschlossen" gilt, wird über `HelpdeskSettingsBL.GetClosedHelpdeskState()` ermittelt. | `HelpdeskBL.cs:433` |
|
||||
| **C-FLOW** | Bezeichnung für das Ticketvorlagen-Feature im Helpdesk-Modul (Ticket-Templates/-Patterns). | `CentronRights.md` Abschnitt 17 |
|
||||
| **Nummernkreis (NumberGroup)** | Mandanten-/filialbezogener Zähler zur Vergabe fortlaufender Belegnummern (z. B. Auftrags-, Rechnungsnummern, Kundennummern). | `NumberGroupBL.cs` |
|
||||
| **ILogic/BLLogic/WSLogic** | Architekturmuster im WPF-Client: `ILogic`-Interface mit zwei Implementierungen, `BL*Logic` (direkter DB-Zugriff) und `WS*Logic` (Webservice-Zugriff), austauschbar je nach `CentronConnectionType`. | `docs/getting-started/general-structure.md` |
|
||||
| **WebServiceBL** | Schicht, die Entities (NHibernate) in DTOs für die Webservice-Schnittstelle konvertiert. | `docs/getting-started/general-structure.md` |
|
||||
| **Result<T>** | Einheitliches Rückgabemuster für Operationen (Erfolg/Warnung/Fehler statt Exceptions als Kontrollfluss); durchgängig in BL-Methoden verwendet. | z. B. `HelpdeskBL.cs` (`Result.AsError(...)`), `NumberGroupBL.cs` |
|
||||
| **Webaccount** | Login-Konto für externe/Kunden-Benutzer (z. B. für WebCart/SelfCare), unterschieden von internen `AppUser`-Konten; eigenes Rechtesystem (`WebAccountsRights`). | `AppRightsBL.CheckWebRightsFromUser`, `README.md` (WebCart) |
|
||||
| **RMA** | Retourenprozess (Return Merchandise Authorization), eigener `CentronObjectKindNumeric`-Wert und eigene SQL-Sonderbehandlung in der Belegverknüpfung. | `ReceiptProgressionBL.cs:84-86` |
|
||||
| **ZUGFeRD/XRechnung** | Elektronisches Rechnungsformat (hybrides PDF+XML bzw. reines XML), für das das System eine eigene Erzeugung/Prüfung implementiert. | `docs/guides/development/xrechnung.md`, Commit `7d62212022` ("ZUGFeRD total check integrity") |
|
||||
| **CentronNexus** | Blazor-Server-basiertes Web-Portal (u. a. Kundenportal/ServiceBoard), ergänzend zum WPF-Desktopclient. | `src/nexus/CentronNexus`, `README.md` |
|
||||
| **ServiceBoard** | Ticketing-/Helpdesk-Oberfläche innerhalb von CentronNexus. | `src/nexus/CentronNexus/ServiceBoard/**` |
|
||||
| **c-entron.NET / c-entron Nexus** | Produktnamen: `c-entron.NET` bezeichnet den WPF-Desktopclient, `c-entron Nexus` das Web-Portal. | `README.md` |
|
||||
|
||||
**Hinweis zur Vollständigkeit:** Dieses Glossar deckt die in dieser Iteration analysierten Bereiche ab (Rechte, Belege/Verkauf, Helpdesk, Login, Lager, Architektur). Für nicht vertieft analysierte Module (z. B. Produktion, Buchhaltung im Detail, EDI-Formate) sind weitere Fachbegriffe zu erwarten, die in Folgeiterationen zu ergänzen sind (siehe `Analysebericht.md`).
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
# Hypothesen
|
||||
|
||||
Sammlung aller mit `[HYPOTHESE]` markierten Aussagen aus StRS/SyRS/SwRS, mit der jeweils offenen Frage, die zur Bestätigung oder Widerlegung fehlt. Sortiert nach Herkunftsdokument.
|
||||
|
||||
| Herkunft | Aussage (verkürzt) | Offene Frage / fehlende Information |
|
||||
|---|---|---|
|
||||
| StRS-010 | Partnerspezifische EDI-Module (Alltron, ALSO, Komsa, …) folgen strukturell demselben Muster und sind daher im Zielsystem konsolidierbar. | Kein Strukturvergleich der einzelnen Partnermodule durchgeführt. Erfordert: Öffnen und Vergleichen der Klassenstrukturen je Partnerordner (Methodensignaturen, gemeinsame Basisklassen/Interfaces). |
|
||||
| StRS-014 / SwRS-008 | Ticketzeiten, die bereits einem Abrechnungsbeleg zugeordnet sind, können nicht mehr verschoben/gelöscht werden. | Kein PRIMÄR-Codebeleg gefunden (nur `CentronRights.md`-Beschreibung). Erfordert: Identifikation und Lektüre der konkreten Timer-BL-Klasse (vermutlich `HelpdeskTimerBL` o. ä., nicht in dieser Iteration lokalisiert) und Prüfung der dortigen Bedingung auf Belegzuordnung. Da abrechnungsrelevant, greift die verschärfte Evidenzanforderung — Anforderung bleibt vollständig als HYPOTHESE markiert, bis PRIMÄR-Beleg vorliegt. |
|
||||
| SyRS-002 / SwRS-003 | Das Sichtbarkeits-Scoping-Muster (All/OnlyOwn/OnlyOwnBranch) aus dem Helpdesk-Modul existiert identisch auch in anderen Modulen (Kalender, Mitarbeiterauslastung). | Nur für Helpdesk im Code verifiziert. Erfordert: Analyse der entsprechenden Kalender-/Mitarbeiterauslastungs-BL-Klassen auf identisches Muster. |
|
||||
| SyRS-007 | Jede Änderung an einem Beleg erzeugt einen `ReceiptLog`-Eintrag (vollständige Protokollierung, nicht nur ausgewählte Ereignisarten). | Es wurde nicht erhoben, an wie vielen und welchen Stellen im Code tatsächlich `ReceiptLog`-Einträge erzeugt werden. Erfordert: Grep auf alle Aufrufstellen, die `ReceiptLog`-Instanzen anlegen, und Abgleich mit den Werten des Enums `ReceiptLogKind`. |
|
||||
| SyRS-010 | Inhaltliche Details/Feldmappings der EDI-Partnerformate sind korrekt und vollständig abgebildet. | Nur strukturelle Existenz der Module geprüft, keine Feldmapping-Analyse. Erfordert: Tiefenanalyse mindestens eines Partnerformats (z. B. ALSO oder Komsa) inkl. Test-Importdatei. |
|
||||
| SyRS-013 | Bei fehlender englischer Übersetzung einer Resource-Zeichenkette greift automatisch ein Fallback auf Deutsch, ohne Fehler. | Konkretes Fallback-Verhalten der .NET-Resource-Manager-Konfiguration bzw. einer projekteigenen Lokalisierungs-Abstraktion wurde nicht im Code verifiziert. Erfordert: Lektüre der Lokalisierungs-Infrastruktur (`docs/guides/ui/localization.md` und zugehöriger Code). |
|
||||
| SwRS-002 | Ein technischer Fehler während `HasUserRight` wird nicht protokolliert (kein Logging im catch-Block). | Nur der eingesehene Ausschnitt von `UserRightsExt.cs` wurde geprüft; ein zentrales, aspektorientiertes Logging außerhalb der Methode wurde nicht ausgeschlossen. Erfordert: Prüfung auf globale Exception-Handler/Logging-Interceptors im Projekt. |
|
||||
| SwRS-003 | Der vierte Sichtbarkeitsmodus `OnlyOwnAndNotify` hat eine eigenständige, im gelesenen Ausschnitt nicht vollständig erschlossene Bedingung. | Der Code vor Zeile 255 der relevanten Methode in `HelpdeskBL.cs` wurde nicht gelesen. Erfordert: vollständige Lektüre der Methode. |
|
||||
| SwRS-004 | Alle hartkodierten numerischen SQL-Literale in `ReceiptProgressionBL.cs` stimmen exakt mit den aktuellen Werten von `CentronObjectKindNumeric` überein. | Kein automatisierter Abgleich Enum-Definition vs. SQL-Literale durchgeführt. Erfordert: Diff/Konsistenzskript oder manueller Zeile-für-Zeile-Abgleich. |
|
||||
| SwRS-010 | Die genaue Bewertungsmethode für den Einkaufspreis bei Wareneingang (gleitender Durchschnitt, FIFO, letzter Preis) ist definiert und konsistent. | `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` wurde nicht gelesen. Erfordert: Analyse dieser Methode. |
|
||||
| SwRS-011 | `ClassContainer` registriert `ILogic`-Implementierungen tatsächlich automatisiert per Namenskonvention (Reflection), wie dokumentiert. | Nur aus `general-structure.md` übernommen, keine Codeverifikation der `ClassContainer`-Klasse selbst. Erfordert: Lektüre von `ClassContainer.cs` (Ort in dieser Iteration nicht identifiziert). |
|
||||
|
||||
## Priorisierungsempfehlung für Folgeiterationen
|
||||
|
||||
Absteigend nach Risiko/Relevanz für eine Web-/SaaS-Neuimplementierung:
|
||||
|
||||
1. **SwRS-008 (Zeiterfassungssperre nach Abrechnung)** — abrechnungsrelevant, aktuell ohne PRIMÄR-Beleg; höchste Priorität gemäß Auftragsvorgabe (strengere Evidenzanforderung für Abrechnungslogik).
|
||||
2. **SwRS-010 (Bewertungsmethode Einkaufspreis)** — direkt bilanz-/kostenrechnungsrelevant.
|
||||
3. **SyRS-007 (Vollständigkeit der Beleg-Protokollierung)** — Audit-/Compliance-relevant.
|
||||
4. **StRS-010 / SyRS-010 (EDI-Feldmappings)** — hohe Änderungsfrequenz laut Commit-Historie, aber bisher nur strukturell erfasst.
|
||||
5. Übrige Hypothesen: geringeres unmittelbares Geschäftsrisiko, aber relevant für Vollständigkeit der Spezifikation.
|
||||
+315
@@ -0,0 +1,315 @@
|
||||
# Stakeholder Requirements Specification (StRS)
|
||||
|
||||
Reverse-engineert aus der Codebasis **c-entron ERP** (Legacy-System, C#/XAML-WPF-Client + ASP.NET-Webservices + Blazor-Portal "CentronNexus", MSSQL-Datenbank via NHibernate). Diese StRS bildet die fachliche/geschäftliche Sicht ab, wie sie sich aus Modulstruktur, Rechtekonzept, UI-Texten und Dokumentation ableiten lässt. Siehe `Analysebericht.md` für Abdeckung/Tiefe je Bereich.
|
||||
|
||||
Format je Anforderung wie in der Aufgabenstellung vorgegeben.
|
||||
|
||||
---
|
||||
|
||||
## Akteursübersicht (aus Rechten/Modulen abgeleitet)
|
||||
|
||||
| Akteur | Beleg für Existenz des Akteurs |
|
||||
|---|---|
|
||||
| Interner Mitarbeiter (`AppUser`) | `Sichmemb`/`AppUser`-Modell, `UserRightsConst.cs` |
|
||||
| Vertriebsmitarbeiter (Sales) | Rechte-Namensraum `UserRightsConst.Sales.*` |
|
||||
| Support-/Helpdesk-Mitarbeiter | `CentronRights.md` Abschnitt "Helpdesk"; `HelpdeskBL.cs` |
|
||||
| Administrator/Systemverwalter | `UserRightsConst.Administration.*`, Modul `Rechteverwaltung` |
|
||||
| Kunde als Web-Benutzer (`WebAccount`) | `AppRightsBL.CheckWebRightsFromUser`, README "WebCart" |
|
||||
| Externes System / EDI-Partner | `src/backend/Centron.BL/EDI/**` (Alltron, ALSO, Komsa, Concerto, EGIS, Zugferd) |
|
||||
| Externe Anwendung (API-Konsument) | `src/webservice/Centron.Interfaces` (`ICentronRestService`), `src/webservice/Centron.Controllers` |
|
||||
|
||||
---
|
||||
|
||||
## StRS-001
|
||||
|
||||
```
|
||||
ID: StRS-001
|
||||
Titel: Rollenbasierte, feingranulare Zugriffssteuerung
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator, alle internen Benutzer
|
||||
Vorbedingung: Ein Administrator verwaltet Benutzergruppen und Rechte im Modul "Rechteverwaltung".
|
||||
Fakt: Es existieren >2800 einzeln vergebbare Rechte-Konstanten (I3D-basiert), organisiert in einer Hierarchie mit Eltern-/Kind-Beziehung (OwnerRecht/NumChildren), zugewiesen an Gruppen, denen wiederum Benutzer angehören.
|
||||
Aussage: Das System soll es Administratoren ermöglichen, jedem internen Benutzer über Gruppenmitgliedschaft eine feingranulare Menge von Einzelrechten zuzuweisen, die den Zugriff auf Module, Datensätze und Funktionen steuert.
|
||||
Ergebnis: Ein Benutzer sieht/bearbeitet nur die Funktionen und Datensätze, für die seine Gruppe(n) freigeschaltet sind.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs - Begründung: 2819 Zeilen mit `public const int`-Rechtekonstanten belegen den Umfang und die Granularität des Rechtekonzepts.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (CheckRightsFromUser) - Begründung: Führt die tatsächliche DB-Prüfung durch (siehe SyRS-001/SwRS-001).
|
||||
- [KONTEXT] docs/guides/development/add-a-new-right.md - Begründung: Beschreibt den Entwicklungsprozess zum Anlegen neuer Rechte inkl. Hierarchie (OwnerRecht, NumChildren) und bestätigt die fachliche Funktionsweise.
|
||||
Prüfidee: Einem Testbenutzer wird eine Gruppe ohne ein bestimmtes Recht zugewiesen; die zugehörige Funktion darf im Client nicht sichtbar/ausführbar sein.
|
||||
Tracelinks: SyRS-001, SwRS-001, SwRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-002
|
||||
|
||||
```
|
||||
ID: StRS-002
|
||||
Titel: Einschränkung von Rechten auf organisatorische Zuständigkeit (Filiale/Eigene Datensätze)
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator, Vertriebsmitarbeiter, Support-Mitarbeiter
|
||||
Vorbedingung: Ein Benutzer besitzt ein Basisrecht (z. B. "Helpdesk anzeigen") sowie optional ein einschränkendes Zusatzrecht.
|
||||
Fakt: Mehrere Rechte sind explizit als "restricting right" dokumentiert und wirken einschränkend auf ein Basisrecht (z. B. SHOW_HELPDESK_ONLY_OWN, SHOW_HELPDESK_ONLY_OWN_BRANCH), nicht additiv.
|
||||
Aussage: Das System soll es erlauben, den Wirkungsbereich einer Berechtigung zusätzlich auf "nur eigene Datensätze" oder "nur eigene Filiale" einzuschränken, um Datensichtbarkeit entlang der Organisationsstruktur zu steuern.
|
||||
Ergebnis: Ein Benutzer mit Basisrecht + Einschränkung sieht ausschließlich die Teilmenge der Datensätze, die der Einschränkung entspricht.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs (GetShowHelpdeskRight-Logik, Zeilen ~269-290) - Begründung: Implementiert konkret die Fallunterscheidung All/OnlyOwn/OnlyOwnBranch/None anhand der geprüften Rechte.
|
||||
- [KONTEXT] CentronRights.md (Abschnitte 1.1, 1.2, 2.1, 4, 7.1) - Begründung: Fachliche Beschreibung der einschränkenden Rechte in eigenen Worten der Entwickler/Dokumentation.
|
||||
Prüfidee: Zwei Testbenutzer unterschiedlicher Filialen mit "nur eigene Filiale"-Recht dürfen jeweils nur Tickets ihrer eigenen Filiale in der Liste sehen.
|
||||
Tracelinks: SyRS-002, SwRS-003
|
||||
Konsolidierung: Kandidat: Gleiches Muster wiederkehrend bei Kalender (RIGHT_KALENDERANZEIGENEIGENE) und Mitarbeiterauslastung (RIGHT_MITARBEITERAUSLASTUNGNUREIGENEFILIALE) — im Zielsystem als generisches "Sichtbarkeits-Scoping" konsolidierbar.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-003
|
||||
|
||||
```
|
||||
ID: StRS-003
|
||||
Titel: Durchgängiger Verkaufsbelegprozess (Angebot bis Rechnung)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Kunde
|
||||
Vorbedingung: Ein Kunde/Interessent existiert im System.
|
||||
Fakt: Die Codebasis modelliert eigenständige Belegtypen Offer (Angebot), Order (Auftrag), DeliveryList (Lieferschein), Invoice (Rechnung) und CreditVoucher (Gutschrift) mit jeweils eigenen Kopf-/Positions-/Versionsentitäten sowie eine BL-Klasse (`ReceiptProgressionBL`), die Ursprungs- und Folgebelege ermittelt.
|
||||
Aussage: Das System soll Vertriebsmitarbeitern ermöglichen, einen Geschäftsvorfall über eine Kette verknüpfter Belege (Angebot → Auftrag → Lieferschein → Rechnung, optional Gutschrift) abzubilden, wobei jeder Folgebeleg auf seinen/seine Ursprungsbeleg(e) rückverfolgbar ist.
|
||||
Ergebnis: Zu jedem Beleg lassen sich vor- und nachgelagerte Belege der Kette anzeigen (Belegverfolgung).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/{Offers,Orders,DeliveryLists,Invoices,CreditVouchers}/*.cs - Begründung: Eigenständige Entitätsklassen je Belegtyp belegen die Modellierung als Kette.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs (CreateOriginReceiptsSql/CreateFollowUpReceiptsSql/GetRelatedItemsForObject) - Begründung: Implementiert die Verknüpfungslogik zwischen den Belegtypen über SQL-Joins auf AufKopf/AufPos/LiefKopf/LiefPos/RechKopf.
|
||||
Prüfidee: Aus einem Auftrag wird ein Lieferschein und daraus eine Rechnung erzeugt; `GetRelatedItemsForObject` für die Rechnung muss Auftrag und Lieferschein als Ursprungsbelege zurückliefern.
|
||||
Tracelinks: SyRS-003, SyRS-004, SwRS-004, SwRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-004
|
||||
|
||||
```
|
||||
ID: StRS-004
|
||||
Titel: Anzahlungsrechnungen vor Auftragsabschluss
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung
|
||||
Vorbedingung: Ein Auftrag existiert und ist noch nicht vollständig abgerechnet.
|
||||
Fakt: `RechKopf` (Rechnung) besitzt ein Feld `DownPaymentForOrderI3D`, über das eine Rechnung explizit einem Auftrag als Anzahlung zugeordnet wird.
|
||||
Aussage: Das System soll die Erfassung von Anzahlungsrechnungen zu einem laufenden Auftrag unterstützen und diese fachlich vom Auftrag aus nachvollziehbar verknüpfen.
|
||||
Ergebnis: Eine Anzahlungsrechnung ist über den Auftrag auffindbar und bei der Belegverfolgung als solche gekennzeichnet (ObjectKind = 4 in der Relations-Abfrage).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs:140-160 (CreateDownPaymentSql) - Begründung: SQL-Statement selektiert `RechKopf` anhand `DownPaymentForOrderI3D = :ObjectI3D`, belegt das Datenmodell und die Verknüpfungsregel.
|
||||
Prüfidee: Für einen Auftrag mit einer Anzahlungsrechnung liefert `GetRelatedItemsForObject(Auftrag)` die Anzahlungsrechnung als verknüpftes Objekt.
|
||||
Tracelinks: SyRS-004, SwRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-005
|
||||
|
||||
```
|
||||
ID: StRS-005
|
||||
Titel: Nachvollziehbarer Lebenszyklus jedes Verkaufsbelegs
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung
|
||||
Vorbedingung: Ein Beleg (z. B. Auftrag) wurde angelegt.
|
||||
Fakt: Es existiert ein einheitliches Enum `ReceiptState` mit den Werten Active ("offen"), Completed ("abgeschlossen"), Canceled ("storniert"), das für Belege verwendet wird.
|
||||
Aussage: Das System soll jedem Verkaufsbeleg einen eindeutigen Status aus der Menge {offen, abgeschlossen, storniert} zuordnen und diesen im weiteren Prozess (Fortschreibung, Reporting) berücksichtigen.
|
||||
Ergebnis: Der Belegstatus ist jederzeit eindeutig bestimmbar und wird konsistent anhand des Enums dargestellt/ausgewertet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Definiert den Status als typsicheres Enum mit fachlichen Beschriftungen.
|
||||
Prüfidee: Ein neu angelegter Beleg hat Status "offen"; nach Stornierung liefert eine Statusabfrage "storniert".
|
||||
Tracelinks: SyRS-005, SwRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-006
|
||||
|
||||
```
|
||||
ID: StRS-006
|
||||
Titel: Eindeutige, lückenfreie Belegnummerierung je Mandant/Filiale
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung, Administrator
|
||||
Vorbedingung: Für einen Beleg-/Objekttyp (Auftrag, Rechnung, Kunde, …) ist ein Nummernkreis konfiguriert.
|
||||
Fakt: `NumberGroupBL.CreateNumberGroups(mandantI3D, branchI3D)` legt Nummernkreise je Mandant/Filiale an; `GetNextNumber` liefert unter Kollisionsvermeidung (Prüfung gegen Zieltabelle) und mit optimistischem Sperren (bedingtes Update, Wiederholschleife) die nächste Nummer.
|
||||
Aussage: Das System soll für Belege und ausgewählte Stammdaten (u. a. Kunden) fortlaufende, pro Mandant/Filiale eindeutige Nummern vergeben, auch bei gleichzeitigem Zugriff mehrerer Benutzer.
|
||||
Ergebnis: Zwei gleichzeitig speichernde Benutzer erhalten garantiert unterschiedliche, fortlaufende Nummern; keine doppelte Vergabe.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs (GetNextNumber, FindNextNumber, Zeilen 50-120) - Begründung: Implementiert Kollisionsprüfung per COUNT(*)-Abfrage und bedingtes Update (`Where(Current == alterWert)`) als nebenläufigkeitssicheren Mechanismus.
|
||||
Prüfidee: Zwei parallele Aufrufe von `GetNextNumber(updateDatabase:true)` für denselben Nummernkreis dürfen keine identische Nummer liefern (Lasttest mit paralleler Ausführung).
|
||||
Tracelinks: SyRS-006, SwRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-007
|
||||
|
||||
```
|
||||
ID: StRS-007
|
||||
Titel: Ticket-/Vorgangsverwaltung im Kundenservice (Helpdesk)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Support-Mitarbeiter, Kunde (indirekt)
|
||||
Vorbedingung: Ein Kundenanliegen (Anfrage, Störung, Auftrag zur Serviceleistung) liegt vor.
|
||||
Fakt: Ein eigenständiges Modul "Helpdesk" mit Entität `Helpdesk`, Kategorisierung (Haupt-/Unterkategorien), Checklisten, Zeiterfassung und konfigurierbarem Status existiert (`HelpdeskBL.cs`, `CentronRights.md`).
|
||||
Aussage: Das System soll die Erfassung, Klassifizierung, Bearbeitung, Zeiterfassung und den Abschluss von Kundenservice-Vorgängen (Tickets) unterstützen.
|
||||
Ergebnis: Ein Ticket durchläuft nachvollziehbar Anlage → Bearbeitung → Abschluss, inkl. erfasster Bearbeitungszeiten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs - Begründung: Zentrale Geschäftslogik für Anlage/Bearbeitung/Rechteprüfung von Tickets.
|
||||
- [KONTEXT] CentronRights.md (Abschnitt "Helpdesk", 18 Unterrechte) - Begründung: Fachliche Beschreibung aller Ticket-bezogenen Handlungen aus Entwicklersicht.
|
||||
Prüfidee: Ein Ticket wird angelegt, bearbeitet, Zeit erfasst und abgeschlossen; jeder Schritt ist im Änderungsprotokoll nachvollziehbar.
|
||||
Tracelinks: SyRS-007, SyRS-008, SwRS-008, SwRS-009
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-008
|
||||
|
||||
```
|
||||
ID: StRS-008
|
||||
Titel: Autorisierungspflicht für Ticketabschluss
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Support-Mitarbeiter
|
||||
Vorbedingung: Ein Ticket soll in den als "geschlossen" konfigurierten Status versetzt werden.
|
||||
Fakt: `HelpdeskBL.CheckUserRigths` prüft beim Setzen des als geschlossen definierten Status explizit das Recht `CLOSE_REQUEST`; ohne dieses Recht wird der Speichervorgang mit Fehlermeldung abgelehnt.
|
||||
Aussage: Das System soll das Schließen eines Tickets nur Benutzern mit dem expliziten Recht "Request abschließen" erlauben, unabhängig vom allgemeinen Bearbeitungsrecht.
|
||||
Ergebnis: Ein Benutzer ohne CLOSE_REQUEST-Recht kann ein Ticket zwar inhaltlich bearbeiten, aber nicht in den Abschluss-Status versetzen (Fehlermeldung "Sie haben nicht das Recht 'Helpdesk abschließen'.").
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:433-439 - Begründung: Bedingte Rechteprüfung direkt vor dem Speichern, durchgesetzte Regel im Code.
|
||||
Prüfidee: Testbenutzer mit EDIT_HELPDESK aber ohne CLOSE_REQUEST versucht, Status auf "geschlossen" zu setzen → erwartet: Fehler-Result, kein Speichern.
|
||||
Tracelinks: SyRS-002, SwRS-009
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-009
|
||||
|
||||
```
|
||||
ID: StRS-009
|
||||
Titel: Bestandsführung für Artikel je Lagerort
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Lagermitarbeiter, Einkauf
|
||||
Vorbedingung: Ein Artikel ist im Artikelstamm angelegt und einem Lager/Lagerort zugeordnet.
|
||||
Fakt: `ArticleStockBL` bietet Methoden zum Lesen (`GetArticleStockInfos`), Erhöhen (`IncreaseArticleStock`) und Fortschreiben (`UpdateArticleStock`) von Bestandsmengen je Artikel/Lagerort sowie zur Fortschreibung des Einkaufspreises bei Wareneingang (`UpdateArticlePurchasePrice`).
|
||||
Aussage: Das System soll den Lagerbestand je Artikel und Lagerort mengenmäßig führen und bei Wareneingängen/-abgängen sowie Bewertungsänderungen (Einkaufspreis) automatisch fortschreiben.
|
||||
Ergebnis: Der abfragbare Bestand entspricht der Summe aller Zu- und Abgänge; der Einkaufspreis wird bei Buchung eines Beleg-Postens aktualisiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs - Begründung: Enthält die konkreten Buchungsmethoden inkl. Verknüpfung zu Beleg/Position (`IReceiptBase`, `IReceiptItemBase`) beim Preis-Update.
|
||||
Prüfidee: Wareneingang über einen Lieferschein erhöht den Bestand des betroffenen Artikels am betroffenen Lagerort um die Liefermenge.
|
||||
Tracelinks: SyRS-009, SwRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-010
|
||||
|
||||
```
|
||||
ID: StRS-010
|
||||
Titel: Elektronischer Datenaustausch mit Lieferanten (EDI)
|
||||
Ebene: StRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Externes System (Lieferant/Großhändler), Einkauf
|
||||
Vorbedingung: Ein EDI-Partner (z. B. Alltron, ALSO, Komsa, Concerto, EGIS) ist konfiguriert.
|
||||
Fakt: Eigene Unterordner/Module je Partner existieren unter `src/backend/Centron.BL/EDI/{Alltron,ALSO,AlsoCH,Komsa,Concerto,EGIS,Opentrans21,SupplierEDI,Zugferd}`.
|
||||
Aussage: Das System soll strukturierte Bestell-, Auftragsbestätigungs- und Rechnungsdaten mit mehreren benannten Großhandels-/Lieferantenpartnern elektronisch austauschen können, inkl. Standardformaten wie OpenTrans 2.1 und ZUGFeRD.
|
||||
Ergebnis: Eingehende Auftragsbestätigungen/Rechnungen der Partner werden importiert und im System referenzierbar gemacht (z. B. EDIHistoryView).
|
||||
Belege:
|
||||
- [PRIMÄR] Verzeichnisstruktur src/backend/Centron.BL/EDI/* (partnerspezifische BL-Klassen) - Begründung: Je Partner eigene Implementierung belegt aktiven, partnerspezifischen Datenaustausch.
|
||||
- [KONTEXT] Commit 3b86043f61 "Fix typo in EDIHistoryView: ... Auftragsbestätigung" - Begründung: Bestätigt operative Nutzung einer EDI-Historienansicht für Auftragsbestätigungen im laufenden Betrieb.
|
||||
- [SEKUNDÄR] docs/guides/development/xrechnung.md - Begründung: Dokumentiert die ZUGFeRD/XRechnung-Unterstützung als bewusste fachliche Anforderung (E-Rechnung).
|
||||
Prüfidee: Eine Testdatei im jeweiligen Partnerformat wird importiert; Ergebnis ist ein systemseitig referenzierbarer Beleg/Belegstatus.
|
||||
Tracelinks: SyRS-010
|
||||
Konsolidierung: Kandidat: Partnerspezifische EDI-Module folgen strukturell ähnlichem Muster (Import/Connector-Klassen) — im Zielsystem als generisches EDI-Adapter-Framework konsolidierbar. [HYPOTHESE: nicht im Detail verglichen, ob die Partner-Implementierungen tatsächlich strukturell identisch sind — Bestätigung erfordert Tiefenanalyse je Partnermodul.]
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-011
|
||||
|
||||
```
|
||||
ID: StRS-011
|
||||
Titel: Web-Portal als Zugang für Kunden und Mitarbeiter (CentronNexus)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Kunde (Web-Benutzer), Mitarbeiter
|
||||
Vorbedingung: Ein Web-Account bzw. Mitarbeiterkonto existiert.
|
||||
Fakt: Ein separates Blazor-Server-Projekt `CentronNexus` mit eigenen Bereichen ServiceBoard (Ticketing), WebCart (Bestellungen), Settings existiert und wird laut Commit-Historie aktiv weiterentwickelt (u. a. 654+ Änderungen im Ordner `ServiceBoard/Customers/CRM/Component`).
|
||||
Aussage: Das System soll neben dem WPF-Desktopclient einen browserbasierten Zugang bereitstellen, über den Kunden Bestellungen/WebCart nutzen und Mitarbeiter Tickets im ServiceBoard bearbeiten können.
|
||||
Ergebnis: Berechtigte Benutzer können sich über CentronNexus einloggen und je nach Rolle Kunden-Self-Service (WebCart) bzw. interne Serviceprozesse (ServiceBoard) nutzen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/ServiceBoard/**, src/nexus/CentronNexus/WebCart/** - Begründung: Eigenständige Verzeichnisstrukturen mit hoher Änderungsfrequenz belegen aktive, produktiv genutzte Funktionsbereiche.
|
||||
- [KONTEXT] README.md Abschnitt "WebCart" - Begründung: Beschreibt fachlichen Zweck (Kunden der Kunden bestellen Sonderpreis-Artikel) in Klartext.
|
||||
Prüfidee: Ein Web-Account meldet sich in CentronNexus an und sieht ausschließlich für ihn freigegebene Artikel (Sonderpreise) im WebCart.
|
||||
Tracelinks: SyRS-011, SyRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-012
|
||||
|
||||
```
|
||||
ID: StRS-012
|
||||
Titel: Duale API-Erreichbarkeit (Web Service und Direktverbindung)
|
||||
Ebene: StRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Systemintegration, externe Anwendungen, mobile/entfernte Clients
|
||||
Vorbedingung: Ein Client (WPF-UI oder externe Anwendung) benötigt Zugriff auf Geschäftsdaten.
|
||||
Fakt: Für jedes Modul wird laut Architekturdokumentation verbindlich sowohl eine direkte DB-Implementierung (`BL*Logic`) als auch eine Webservice-Implementierung (`WS*Logic`) hinter einem gemeinsamen `ILogic`-Interface gefordert; Module deklarieren unterstützte Verbindungsarten (`CentronConnectionType[]`).
|
||||
Aussage: Das System soll denselben fachlichen Funktionsumfang sowohl über eine direkte Datenbankverbindung als auch über eine Webservice-Schnittstelle anbieten, sodass Clients ohne Funktionsverlust zwischen beiden Zugriffsarten wechseln können.
|
||||
Ergebnis: Ein Client kann konfigurationsgesteuert zwischen SqlServer-Direktzugriff und CentronWebServices umgeschaltet werden, ohne dass sich das aufrufende ViewModel ändert.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/getting-started/general-structure.md (Abschnitt "Dual Implementation Architecture") - Begründung: Explizit als "MUST implement both" dokumentierte Pflichtarchitektur, im Repository als Entwicklerregel hinterlegt.
|
||||
Prüfidee: Für ein beliebiges Modul existieren sowohl eine `BL{Modul}Logic`- als auch eine `WS{Modul}Logic`-Klasse, die dasselbe `I{Modul}Logic`-Interface implementieren.
|
||||
Tracelinks: SyRS-012, SwRS-011
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-013
|
||||
|
||||
```
|
||||
ID: StRS-013
|
||||
Titel: Deutschsprachige Benutzerführung als Marktanforderung
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional
|
||||
Akteur: alle Benutzer (primär deutschsprachiger Markt)
|
||||
Vorbedingung: Neue UI-Texte/Fehlermeldungen werden entwickelt.
|
||||
Fakt: Die Entwicklungsdokumentation schreibt verbindlich vor, dass alle UI-Labels, Benutzermeldungen und Fehlermeldungen auf Deutsch verfasst werden, mit Englisch als zusätzlicher Übersetzung über separate Resource-Dateien.
|
||||
Aussage: Das System soll primär für den deutschsprachigen Markt ausgelegt sein: alle benutzersichtbaren Texte sind auf Deutsch zu verfassen, mit optionaler englischer Übersetzung.
|
||||
Ergebnis: Neue Funktionen sind ab Werk vollständig auf Deutsch nutzbar; Englisch ist eine zusätzliche, nicht verpflichtend vollständige Option.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md (Abschnitt "German-First Language Policy") - Begründung: Explizite, im Repository dokumentierte Vorgabe für alle neuen UI-Texte.
|
||||
- [KONTEXT] Durchgängig deutsche Fehlermeldungen in Code, z. B. HelpdeskBL.cs ("Sie haben nicht das Recht ...") - Begründung: Bestätigt die gelebte Praxis im bestehenden Code.
|
||||
Prüfidee: Stichprobe von 20 zufälligen benutzersichtbaren Strings im WPF-Client: alle sind auf Deutsch vorhanden (Basis-resx).
|
||||
Tracelinks: SyRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## StRS-014
|
||||
|
||||
```
|
||||
ID: StRS-014
|
||||
Titel: Zeiterfassung als Abrechnungsgrundlage im Kundenservice
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Support-Mitarbeiter, Buchhaltung
|
||||
Vorbedingung: Ein Ticket ist angelegt und wird bearbeitet.
|
||||
Fakt: Für Tickets existieren dedizierte Rechte "Zeiten bearbeiten" (EDIT_TIME), "nur eigene Zeiten" (OWN_TIME_EDIT), "Helpdeskzeiten verschieben"/"löschen", jeweils mit der expliziten Einschränkung "aber nur wenn das Ticket nicht Teil eines Belegs ist"; zusätzlich existiert `CreateReceiptForHelpdeskTimers` zur Erzeugung von Rechnungspositionen aus erfassten Ticketzeiten.
|
||||
Aussage: Das System soll erfasste Bearbeitungszeiten an Tickets als Grundlage für die Abrechnung (Erzeugung von Rechnungspositionen) verwenden und deren nachträgliche Änderung/Löschung sperren, sobald sie einem Abrechnungsbeleg zugeordnet sind.
|
||||
Ergebnis: Eine bereits abgerechnete Zeitbuchung kann nicht mehr verschoben oder gelöscht werden; nicht abgerechnete Zeiten sind änderbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/DataAndResults/CreateReceiptForHelpdeskTimers/* - Begründung: Eigene BL-Struktur zur Umwandlung von Ticketzeiten in Belegpositionen.
|
||||
- [KONTEXT] CentronRights.md Abschnitte 8, 9 ("... aber nur, wenn das Ticket nicht Teil eines Belegs ist") - Begründung: Fachliche Beschreibung der Sperrregel in Entwicklerdokumentation.
|
||||
Prüfidee: Eine bereits abgerechnete Zeitbuchung eines Tickets kann über EDIT_TIME nicht mehr gelöscht werden (erwarteter Fehler).
|
||||
Tracelinks: SyRS-007, SwRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: konkrete Sperrbedingung "ist Teil eines Belegs" wurde nur aus CentronRights.md übernommen, nicht im Code von HelpdeskBL.cs verifiziert — Bestätigung erfordert Analyse der Timer-BL-Klassen.]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Ende StRS – 14 Anforderungen. Fortsetzung/Vertiefung in Folgeiterationen vorgesehen, siehe `Analysebericht.md`.*
|
||||
+272
@@ -0,0 +1,272 @@
|
||||
# Software Requirements Specification (SwRS)
|
||||
|
||||
Komponenten-, Datenmodell- und software-interne Regeln, die die SyRS-Anforderungen konkret realisieren. Technische Bezeichner (Klassen, Methoden, Tabellen, Spalten) bleiben im Original.
|
||||
|
||||
---
|
||||
|
||||
## SwRS-001
|
||||
|
||||
```
|
||||
ID: SwRS-001
|
||||
Titel: SQL-Join-Implementierung der Rechteprüfung
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente AppRightsBL
|
||||
Vorbedingung: `CheckRightsFromUser(appUserI3D, rightI3Ds)` wird mit einer Benutzer-I3D und einer Liste angefragter Recht-I3Ds aufgerufen.
|
||||
Fakt: Die Methode führt exakt folgendes SQL aus: `SELECT st.Recht AS ID FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D AND st.Recht IN (:RightI3Ds)` und gibt die Liste der tatsächlich zugewiesenen Recht-IDs zurück (Teilmenge der Anfrage, keine Fehlermeldung bei fehlendem Recht).
|
||||
Aussage: Die Komponente AppRightsBL soll bei `CheckRightsFromUser` ausschließlich diejenigen Recht-IDs aus der Anfrageliste zurückgeben, die dem Benutzer über mindestens eine seiner Gruppen tatsächlich zugewiesen sind; nicht zugewiesene IDs fehlen ersatzlos im Ergebnis (kein Fehlerwert, keine Exception).
|
||||
Ergebnis: Der Aufrufer muss das Ergebnis explizit mittels `.Contains(RechtID)` prüfen, um auf fehlende Rechte zu reagieren.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:95-111 - Begründung: Wörtliches SQL-Statement, direkt einsehbar im Code, keine Interpretation nötig.
|
||||
- [SEKUNDÄR] docs/guides/development/check-userrights.md - Begründung: Zeigt das erwartete Aufrufmuster `.Contains(...)` beim Konsumenten und bestätigt die "Teilmenge statt Fehler"-Semantik.
|
||||
Prüfidee: Unit-Test ruft CheckRightsFromUser mit einer Mischung aus zugewiesenen/nicht zugewiesenen Recht-IDs auf; Ergebnisliste enthält exakt die zugewiesene Teilmenge.
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-002
|
||||
|
||||
```
|
||||
ID: SwRS-002
|
||||
Titel: Fail-Closed-Verhalten bei Rechteprüfungsfehlern
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente UserRightsExt
|
||||
Vorbedingung: `AppUser.HasUserRight(RightID)` wird aufgerufen, z. B. während einer DB-Verbindungsstörung.
|
||||
Fakt: `HasUserRight` umschließt den gesamten Prüfaufruf mit `try { ... } catch { return false; }`; jede Exception (z. B. Verbindungsfehler, Nullreferenz) wird stillschweigend abgefangen und als "kein Recht" gewertet, ebenso `IsAdmin`.
|
||||
Aussage: Die Komponente UserRightsExt soll bei jedem technischen Fehler während einer Rechte- oder Adminprüfung konservativ mit "nicht berechtigt" (false) antworten, anstatt die Exception weiterzureichen oder implizit Zugriff zu gewähren.
|
||||
Ergebnis: Ein technischer Fehler in der Rechteprüfung führt nie zu unbeabsichtigter Rechtevergabe (fail-closed), kann aber auch legitime Zugriffe fälschlich verweigern, ohne dass dies für den Aufrufer als Fehler erkennbar ist (verschluckte Exception).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs:18-32,56-66 - Begründung: Wörtlicher try/catch-Block mit `return false` im catch, durchgesetztes Verhalten im Code.
|
||||
Prüfidee: Simulation einer Exception innerhalb der Session-Erzeugung während `HasUserRight`-Aufruf: Rückgabewert ist `false`, keine Exception propagiert zum Aufrufer.
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Das verschluckte Fehlerverhalten kann Diagnoseprobleme verursachen (falsche "keine Berechtigung"-Meldungen bei reinen Infrastrukturfehlern) — ob dies protokolliert wird, ist im gesichteten Code nicht erkennbar (kein Logging-Aufruf im catch-Block sichtbar).]
|
||||
```
|
||||
|
||||
## SwRS-003
|
||||
|
||||
```
|
||||
ID: SwRS-003
|
||||
Titel: Vierwertige Sichtbarkeitsklassifikation im Helpdesk
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente HelpdeskBL
|
||||
Vorbedingung: Ermittlung der Ticket-Sichtbarkeit für einen Benutzer.
|
||||
Fakt: Ein internes Enum/Wertebereich `ShowHelpdeskRight` mit den Ausprägungen `All`, `OnlyOwnBranch`, `OnlyOwn`, `OnlyOwnAndNotify`, `None` wird anhand der geprüften Rechte SHOW_HELPDESK/_ONLY_OWN/_ONLY_OWN_BRANCH sowie einer weiteren, im gesichteten Ausschnitt nicht vollständig erschlossenen "Notify"-Bedingung ermittelt.
|
||||
Aussage: Die Komponente HelpdeskBL soll die Sichtbarkeit von Tickets für einen Benutzer als einen von mindestens vier klar definierten Modi klassifizieren, wobei "kein SHOW_HELPDESK-Recht" zwingend zu `None` (keine Sichtbarkeit) führt.
|
||||
Ergebnis: Nachgelagerte Filterlogik kann anhand des ermittelten Modus eindeutig entscheiden, welche Ticketmenge zulässig ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:245-291 - Begründung: Direkt sichtbare Fallunterscheidung mit Rückgabewerten `ShowHelpdeskRight.*`.
|
||||
Prüfidee: Für alle 2^3 Kombinationen der drei Basisrechte liefert die Methode den in der Tabelle der Fallunterscheidung dokumentierten Modus.
|
||||
Tracelinks: SyRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Die genaue Bedingung für `OnlyOwnAndNotify` (Zeilen vor 255) wurde nicht vollständig gelesen/zitiert — Herkunft und Zweck dieses vierten Modus benötigt weitere Codeanalyse.]
|
||||
```
|
||||
|
||||
## SwRS-004
|
||||
|
||||
```
|
||||
ID: SwRS-004
|
||||
Titel: Objektart-Enum als Diskriminator für Belegtypen (CentronObjectKindNumeric)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ReceiptProgressionBL, Datenmodell
|
||||
Vorbedingung: Ein Beleg-Objekt wird typisiert referenziert (für Verknüpfungsabfragen, externe Referenzen, Logging).
|
||||
Fakt: Der SQL-Code verwendet feste numerische Codes für Belegarten, u. a. `1 = OrderPos` (Auftragsposition, im externen Referenz-Statement), `2 = DeliveryList`/Order (kontextabhängig), `3 = DeliveryListPos`, `4 = Invoice/Down-Payment-Invoice`; die Codes stammen aus dem Enum `CentronObjectKindNumeric`.
|
||||
Aussage: Das System soll jeden Belegtyp und jede Belegposition durch einen festen, numerischen `CentronObjectKindNumeric`-Wert eindeutig identifizieren, der als Diskriminator in Referenz-, Log- und Verknüpfungsstrukturen (u. a. `ObjectExternalReferences.ObjectKind`, `ReceiptLog.ReceiptKind`) verwendet wird.
|
||||
Ergebnis: Aus einem (I3D, ObjectKind)-Paar lässt sich eindeutig sowohl der Datensatz als auch dessen fachlicher Belegtyp bestimmen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs:120-166 - Begründung: Wörtliche Verwendung der numerischen Codes in SQL-CASE-Ausdrücken belegt den Diskriminator-Charakter.
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptLog.cs:10 (`ReceiptKind` vom Typ `CentronObjectKindNumeric`) - Begründung: Zeigt Wiederverwendung desselben Enums in einer unabhängigen Komponente (Audit-Log), bestätigt systemweite Gültigkeit.
|
||||
Prüfidee: Für jeden in ReceiptProgressionBL verwendeten numerischen Code existiert ein korrespondierender, namentlich passender Enum-Wert in `CentronObjectKindNumeric` (Konsistenzprüfung Enum vs. SQL-Literale).
|
||||
Tracelinks: SyRS-003, SyRS-004, SyRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround - Begründung: Hartkodierte numerische Literale in SQL-Strings (statt Verweis auf das Enum selbst, z. B. `(int)CentronObjectKindNumeric.X`) sind an mehreren Stellen erkennbar (z. B. `2 AS ObjectKind` ohne Cast) und bergen ein Inkonsistenzrisiko bei künftigen Enum-Änderungen.
|
||||
```
|
||||
|
||||
## SwRS-005
|
||||
|
||||
```
|
||||
ID: SwRS-005
|
||||
Titel: Datenmodell der Anzahlungsrechnung
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Datenmodell (Tabelle RechKopf)
|
||||
Vorbedingung: Eine Rechnung wird als Anzahlung zu einem Auftrag angelegt.
|
||||
Fakt: Die Tabelle `RechKopf` besitzt die nullable Spalte `DownPaymentForOrderI3D`; ist sie gesetzt, wird die Rechnung in `CreateDownPaymentSql` als verknüpftes Objekt vom Typ `4` (Invoice) zum referenzierten Auftrag geliefert.
|
||||
Aussage: Das Datenmodell soll die Anzahlungsbeziehung einer Rechnung zu einem Auftrag als einfache Fremdschlüsselreferenz (`DownPaymentForOrderI3D`) auf der Rechnungskopf-Tabelle abbilden, ohne eigene Zwischentabelle.
|
||||
Ergebnis: Eine Rechnung kann höchstens einem Auftrag als Anzahlung zugeordnet sein (1:n vom Auftrag aus, n:1 von der Rechnung aus).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs:140-153 - Begründung: SQL-Statement referenziert die Spalte direkt in WHERE-Klausel.
|
||||
Prüfidee: Rechnung mit gesetztem `DownPaymentForOrderI3D` erscheint bei Abfrage der verknüpften Objekte des referenzierten Auftrags.
|
||||
Tracelinks: SyRS-003, SyRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-006
|
||||
|
||||
```
|
||||
ID: SwRS-006
|
||||
Titel: Enum-zu-UI-Text-Zuordnung für Belegstatus
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ReceiptState/ReceiptStateExtensions
|
||||
Vorbedingung: Der Belegstatus soll dem Benutzer angezeigt werden.
|
||||
Fakt: `ReceiptState` trägt pro Enum-Wert ein `[Description]`-Attribut (offen/abgeschlossen/storniert); zusätzlich existiert eine Extension-Methode `GetReceiptStateString()` mit identischer switch-Zuordnung (redundante Definition derselben Zuordnung an zwei Stellen).
|
||||
Aussage: Das System soll jedem `ReceiptState`-Wert eine feste deutsche Anzeigebezeichnung zuordnen (offen/abgeschlossen/storniert), konsistent über alle Stellen, die den Status anzeigen.
|
||||
Ergebnis: Jede UI-Stelle, die den Belegstatus anzeigt, zeigt einen der drei definierten deutschen Begriffe.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Enum mit Description-Attributen und Extension-Methode als vollständiger, einsehbarer Code.
|
||||
Prüfidee: Für jeden Enum-Wert liefern sowohl das Description-Attribut als auch `GetReceiptStateString()` denselben deutschen Text (Konsistenzprüfung der doppelten Definition).
|
||||
Tracelinks: SyRS-005
|
||||
Konsolidierung: Kandidat: Zwei redundante Zuordnungen (Attribut + switch-Methode) für dieselbe Information — im Zielsystem auf eine einzige Quelle konsolidierbar.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-007
|
||||
|
||||
```
|
||||
ID: SwRS-007
|
||||
Titel: Compare-and-Swap-Update für Nummernkreis-Zähler
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente NumberGroupBL, Tabelle NumberGroup
|
||||
Vorbedingung: `GetNextNumber(numberGroup, numberGroupObject, updateDatabase:true)` wird aufgerufen.
|
||||
Fakt: Die Methode liest zunächst `numberGroupObject.Current`, berechnet mittels `FindNextNumber` (Grundwert + `Interval`, danach Kollisionsprüfung per `SELECT COUNT(*)` gegen die per `numberGroup.GetTableName()/GetFieldName()` bestimmte Zieltabelle/-spalte) den nächsten freien Wert und aktualisiert die Datenbank nur, wenn `Current` zum Zeitpunkt des Updates noch dem zuvor gelesenen Wert entspricht (`Query<NumberGroup>().Where(f => f.I3D == ... && f.Current == numberGroupObject.Current).Set(s => s.Current, nextNumber).Update()`); bei 0 betroffenen Zeilen wird die gesamte Schleife wiederholt.
|
||||
Aussage: Die Komponente NumberGroupBL soll den nächsten Wert eines Nummernkreises ausschließlich über ein bedingtes Update (Compare-and-Swap) fortschreiben und bei Konflikt automatisch neu ermitteln, ohne Datenbanksperren über die Transaktionsgrenze hinweg zu halten.
|
||||
Ergebnis: Der Zähler wird nie doppelt vergeben; unter hoher Nebenläufigkeit steigt die Anzahl der Wiederholungen, aber nicht die Fehlerquote.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:62-135 - Begründung: Vollständig einsehbare Implementierung des CAS-Musters inkl. Kollisionsprüfung gegen Zieltabelle.
|
||||
- [KONTEXT] NumberGroupBL.cs:76-79 (Kommentar "SKA: Why we dont use the object update ... safety measure") - Begründung: Entwicklerkommentar bestätigt die bewusste Design-Entscheidung für dieses Muster.
|
||||
Prüfidee: Zwei parallele Transaktionen mit demselben Ausgangswert `Current`: nur eine darf erfolgreich committen, die andere muss die Schleife erneut durchlaufen und einen anderen Wert erhalten.
|
||||
Tracelinks: SyRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-008
|
||||
|
||||
```
|
||||
ID: SwRS-008
|
||||
Titel: Sperrung der Zeiterfassungsänderung nach Abrechnung [HYPOTHESE]
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Komponente Helpdesk-Zeiterfassung
|
||||
Vorbedingung: Eine Ticketzeit wurde bereits einem Beleg (Rechnung) zugeordnet.
|
||||
Fakt: Keine im Rahmen dieser Iteration gelesene Codezeile belegt die Sperrbedingung direkt; die Regel ist ausschließlich aus `CentronRights.md` ("... aber nur, wenn das Ticket nicht Teil eines Belegs ist", Abschnitte 8 und 9) bekannt.
|
||||
Aussage: [HYPOTHESE] Das System soll das Verschieben und Löschen von Ticketzeiten verhindern, sobald diese Zeiten einem abrechnungsrelevanten Beleg zugeordnet wurden.
|
||||
Ergebnis: [HYPOTHESE] Ein Versuch, eine bereits abgerechnete Zeitbuchung zu löschen/verschieben, wird mit Fehlermeldung abgelehnt.
|
||||
Belege:
|
||||
- [KONTEXT] CentronRights.md, Abschnitte 8 ("Helpdeskzeiten verschieben") und 9 ("Helpdeskzeiten löschen") - Begründung: Einzige verfügbare Quelle; Entwicklerdokumentation, kein Code-Constraint gesichtet.
|
||||
Prüfidee: Suche nach der konkreten Prüfmethode (voraussichtlich in einer `HelpdeskTimer*BL`-Klasse) und Verifikation der Bedingung im Code als Folgeschritt.
|
||||
Tracelinks: StRS-014
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE - Begründung für fehlende Bestätigung: Die konkrete Timer-BL-Implementierungsklasse wurde in dieser Iteration nicht identifiziert/gelesen; nur die Dokumentationsaussage liegt vor. Sicherheits-/Abrechnungsrelevanz erfordert laut Auftrag mindestens einen PRIMÄR-Beleg, der hier fehlt.
|
||||
```
|
||||
|
||||
## SwRS-009
|
||||
|
||||
```
|
||||
ID: SwRS-009
|
||||
Titel: Statusgesteuerte Zeitstempel-Rücksetzung (ClosedAt)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente HelpdeskBL
|
||||
Vorbedingung: Ein Ticket wird gespeichert, dessen Status vom konfigurierten Abschlussstatus abweicht.
|
||||
Fakt: In `CheckUserRigths` wird im `else`-Zweig (Status ≠ konfigurierter Abschlussstatus) unbedingt `entity.ClosedAt = null` gesetzt, unabhängig vom vorherigen Wert.
|
||||
Aussage: Die Komponente HelpdeskBL soll das Feld `ClosedAt` eines Tickets automatisch auf `null` zurücksetzen, sobald der Ticketstatus nicht mehr dem konfigurierten Abschlussstatus entspricht.
|
||||
Ergebnis: `ClosedAt` ist genau dann ungleich `null`, wenn sich das Ticket zuletzt im Abschlussstatus befunden hat (kein "Abschlussdatum" für aktuell offene Tickets).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:440-443 - Begründung: Unbedingte Zuweisung im else-Zweig, direkt einsehbar.
|
||||
Prüfidee: Ticket im Abschlussstatus mit gesetztem ClosedAt wird auf "in Bearbeitung" umgestellt → nach Speichern ist ClosedAt == null.
|
||||
Tracelinks: SyRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-010
|
||||
|
||||
```
|
||||
ID: SwRS-010
|
||||
Titel: Verkettung von Mengen- und Preisfortschreibung bei Wareneingang
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ArticleStockBL
|
||||
Vorbedingung: `UpdateArticlePurchasePrice` wird mit einem Beleg/einer Position, altem und neuem Mengen-/Preiswert aufgerufen.
|
||||
Fakt: Die Methode liest den bisherigen Preis aus `SecondaryStockArticle` (Filter auf Artikel-I3D und Lager-I3D), berechnet daraus einen neuen Wert und delegiert die eigentliche Fortschreibung an `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking`, welches Beleg, Position, Lager sowie alte/neue Menge und alten/neuen Preis als Parameter erhält.
|
||||
Aussage: Die Komponente ArticleStockBL soll bei jeder wareneingangsbedingten Preisänderung den bisherigen lagerortspezifischen Einkaufspreis als Referenzwert heranziehen und die Fortschreibung an eine zentrale Artikelpreis-Komponente delegieren, statt den Bestand isoliert zu aktualisieren.
|
||||
Ergebnis: Der resultierende Einkaufspreis eines Artikels ist konsistent mit dem zuletzt gebuchten Beleg/Posten nachvollziehbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs:74-148 - Begründung: Konkrete Methodensignatur und Delegation an ArticleBL belegen den durchgesetzten Ablauf.
|
||||
Prüfidee: Zwei aufeinanderfolgende Wareneingänge mit unterschiedlichem Einkaufspreis führen zu einem im Artikel/Lagerort konsistent nachvollziehbaren, aktualisierten Preis (z. B. gleitender Durchschnitt oder letzter Preis – exakte Bewertungsmethode nicht Teil dieses Belegs).
|
||||
Tracelinks: SyRS-009
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Die genaue Bewertungsformel (gleitender Durchschnitt vs. FIFO vs. letzter Einstandspreis) wird in `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` festgelegt, welches in dieser Iteration nicht gelesen wurde.]
|
||||
```
|
||||
|
||||
## SwRS-011
|
||||
|
||||
```
|
||||
ID: SwRS-011
|
||||
Titel: Namenskonventionsbasierte Auto-Registrierung von Logic-Implementierungen
|
||||
Ebene: SwRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Komponente ClassContainer
|
||||
Vorbedingung: Ein Modul definiert `I{Modul}Logic`, `BL{Modul}Logic` und `WS{Modul}Logic` nach Namenskonvention.
|
||||
Fakt: Laut Architekturdokumentation registriert `ClassContainer` die passende Implementierung automatisch, "wenn die Namenskonventionen befolgt werden" ("If the naming guidelines are followed, the client will automatically register the ILogic with the corresponding BLLogic and WSLogic").
|
||||
Aussage: Die Komponente ClassContainer soll zur Laufzeit anhand des Namensmusters `I{X}Logic`/`BL{X}Logic`/`WS{X}Logic` automatisch die passende Implementierung für Dependency Injection registrieren, ohne manuelle Registrierung je Modul.
|
||||
Ergebnis: Ein neues Modul, das die Namenskonvention einhält, ist ohne zusätzlichen Registrierungscode nutzbar.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md (Abschnitt "ClassContainer and ILogic Pattern") - Begründung: Repository-interne Dokumentation beschreibt den Mechanismus, jedoch wurde die konkrete Reflection-/Registrierungsimplementierung in `ClassContainer` selbst in dieser Iteration nicht gelesen (daher SEKUNDÄR statt PRIMÄR).
|
||||
Prüfidee: Neues Test-Modul mit korrektem Namensschema wird ohne expliziten Registrierungsaufruf über `ClassContainer.Instance.WithInstance<I...Logic>()` auflösbar.
|
||||
Tracelinks: SyRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Die genaue Auto-Registrierungsimplementierung (Reflection-Scan, Konventionsprüfung, Fehlerverhalten bei Namensabweichung) wurde nicht im Quellcode von ClassContainer selbst verifiziert, sondern nur aus der Dokumentation übernommen.]
|
||||
```
|
||||
|
||||
## SwRS-012
|
||||
|
||||
```
|
||||
ID: SwRS-012
|
||||
Titel: Separates Rechte-Datenmodell für Web-Accounts
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Datenmodell (Tabelle WebAccountsRights)
|
||||
Vorbedingung: Ein WebAccount fordert eine rechtebehaftete Web-Operation an.
|
||||
Fakt: `CheckWebRightsFromUser` verwendet das SQL `SELECT WAR.WebRightsI3D AS ID FROM WebAccountsRights WAR WHERE WAR.WebAccountsI3D = :WebAccountI3D AND WAR.WebRightsI3D IN (:WebRightI3Ds)` – eine eigenständige, flache Zuordnungstabelle ohne Gruppenkonzept (im Unterschied zu internen Benutzern).
|
||||
Aussage: Das Datenmodell soll WebAccount-Rechte direkt (1:n, ohne Gruppenzwischenschicht) in `WebAccountsRights` zuordnen, im Gegensatz zum gruppenbasierten Modell interner Benutzer.
|
||||
Ergebnis: Jedes WebAccount-Recht wird individuell je Konto vergeben; es existiert kein Konzept "Web-Rechtegruppe" auf Datenebene.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:113-130 - Begründung: SQL zeigt direkte Konto-Recht-Zuordnung ohne Gruppentabelle.
|
||||
Prüfidee: Datenmodellprüfung: `WebAccountsRights` besitzt keine Fremdschlüsselspalte auf eine Gruppentabelle (Strukturvergleich mit `Sichtrus`/`Sichmemb`).
|
||||
Tracelinks: SyRS-011
|
||||
Konsolidierung: Kandidat: Zwei parallele, strukturell unterschiedliche Rechtemodelle (gruppenbasiert für AppUser, direkt für WebAccount) — im Zielsystem ggf. auf ein einheitliches RBAC-Modell konsolidierbar.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SwRS-013
|
||||
|
||||
```
|
||||
ID: SwRS-013
|
||||
Titel: SHA-1-basierte Passwort-Hash-Funktion mit fester Kodierung
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente SHA1Decoder
|
||||
Vorbedingung: Ein Passwort (Klartext) soll gehasht werden.
|
||||
Fakt: `SHA1Decoder.GetDecodedSHA1String` kodiert den Eingabetext explizit mit Codepage 1252 (ANSI Latin 1/Windows), berechnet SHA-1 und gibt den Hash als kleingeschriebenen Hex-String ohne Trennzeichen zurück; kein Salt-Parameter in der Signatur vorhanden.
|
||||
Aussage: Die Komponente SHA1Decoder soll Passwörter deterministisch (ohne Salt) über SHA-1 auf Basis der Kodierung Windows-1252 hashen; identische Klartexte erzeugen stets identische Hashwerte.
|
||||
Ergebnis: Zwei Benutzer mit identischem Passwort besitzen identische Hash-Werte in der Datenbank (erkennbar bei DB-Zugriff), da kein Salt verwendet wird.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Common/TextCoding/SHA1Decoder.cs - Begründung: Vollständige, kurze Implementierung ohne Salt-Parameter, direkt einsehbar.
|
||||
Prüfidee: Zwei AppUser-Datensätze mit demselben Testpasswort erzeugen identische Werte in der Spalte `Password`.
|
||||
Tracelinks: SyRS-014
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround - Begründung: Deterministisches, unsalted SHA-1-Hashing ist nach heutigem Stand der Technik nicht mehr empfohlen (Rainbow-Table-Anfälligkeit, fehlende adaptive Kostenfunktion); für die Web-/SaaS-Neuimplementierung priorisiert zu prüfen.
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Ende SwRS – 13 Anforderungen (davon 1 vollständig als HYPOTHESE markiert: SwRS-008).*
|
||||
+311
@@ -0,0 +1,311 @@
|
||||
# System Requirements Specification (SyRS)
|
||||
|
||||
Systemverhalten, Schnittstellen sowie Performance-/Sicherheitsanforderungen, abgeleitet aus den StRS-Anforderungen und zusätzlichen technischen Beobachtungen. Nicht-funktionale Anforderungen sind zusätzlich einem Qualitätsmerkmal nach **ISO/IEC 25010** zugeordnet (Feld `Typ`).
|
||||
|
||||
---
|
||||
|
||||
## SyRS-001
|
||||
|
||||
```
|
||||
ID: SyRS-001
|
||||
Titel: Serverseitige Rechteprüfung gegen Gruppenmitgliedschaft
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (BL-Schicht), interner Benutzer
|
||||
Vorbedingung: Ein authentifizierter Benutzer (AppUser) fordert eine rechtebehaftete Operation an.
|
||||
Fakt: `AppRightsBL.CheckRightsFromUser` führt für die angefragten Recht-IDs eine SQL-Abfrage aus, die über `Sichtrus` (Gruppe→Recht) und `Sichmemb` (Benutzer→Gruppe) verknüpft und nur tatsächlich zugewiesene Rechte zurückgibt.
|
||||
Aussage: Das System soll bei jeder rechtebehafteten Operation serverseitig (nicht nur clientseitig) prüfen, ob der anfragende Benutzer über seine Gruppenmitgliedschaften das erforderliche Recht besitzt.
|
||||
Ergebnis: Eine Anfrage für ein nicht zugewiesenes Recht liefert eine leere/negative Ergebnismenge und die aufrufende Operation wird mit Fehler abgebrochen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:95-111 (CheckRightsFromUser) - Begründung: Rohes SQL mit JOIN Sichtrus/Sichmemb, direkt durchgesetzte DB-Abfrage, keine reine Client-Prüfung.
|
||||
Prüfidee: Direkter Aufruf von `CheckRightsFromUser` mit der I3D eines Rechts, das keiner Gruppe des Benutzers zugewiesen ist, liefert eine leere Liste.
|
||||
Tracelinks: StRS-001; SwRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-002
|
||||
|
||||
```
|
||||
ID: SyRS-002
|
||||
Titel: Sichtbarkeits-Scoping von Datensätzen anhand einschränkender Rechte
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System, Support-Mitarbeiter, Vertriebsmitarbeiter
|
||||
Vorbedingung: Ein Benutzer ruft eine Liste rechtebehafteter Datensätze ab (z. B. Ticketliste).
|
||||
Fakt: `HelpdeskBL` ermittelt aus der Kombination der Rechte SHOW_HELPDESK/_ONLY_OWN/_ONLY_OWN_BRANCH einen von vier möglichen Sichtbarkeitsmodi (All/OnlyOwn/OnlyOwnBranch/None), der anschließend als Filterkriterium für die Datenabfrage dient.
|
||||
Aussage: Das System soll bei Listen-/Suchabfragen serverseitig einen Sichtbarkeitsfilter aus den Rechten des anfragenden Benutzers ableiten und ausschließlich die dadurch zulässige Teilmenge zurückliefern.
|
||||
Ergebnis: Die Ergebnisliste enthält nie Datensätze außerhalb des ermittelten Sichtbarkeitsbereichs, unabhängig vom clientseitigen UI-Zustand.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs (Methode zur Ermittlung von `ShowHelpdeskRight`, Zeilen ~245-291) - Begründung: Serverseitige BL-Methode, kein reiner UI-Code.
|
||||
Prüfidee: Benutzer mit SHOW_HELPDESK_ONLY_OWN_BRANCH erhält bei Ticketsuche ausschließlich Tickets seiner Filiale, auch bei explizitem Filterversuch auf andere Filialen.
|
||||
Tracelinks: StRS-002; SwRS-003
|
||||
Konsolidierung: Kandidat: identisches Scoping-Muster (All/OnlyOwn/OnlyOwnBranch) potenziell in weiteren Modulen (Kalender, Mitarbeiterauslastung) — nur für Helpdesk verifiziert, für andere Module [HYPOTHESE].
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-003
|
||||
|
||||
```
|
||||
ID: SyRS-003
|
||||
Titel: Bidirektionale Belegverknüpfung (Ursprung/Folge) über Objektreferenzen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Mindestens zwei Belege derselben Kette existieren (z. B. Auftrag und daraus erzeugter Lieferschein).
|
||||
Fakt: `ReceiptProgressionBL.GetRelatedItemsForObject` liefert für ein Beleg-Objekt (`CentronEntityReference`/`ExternalObjectEntityReference`) sowohl Ursprungs- als auch Folgebelege über UNION-ALL-SQL-Abfragen mit einem `IsOrigin`-Flag zur Unterscheidung der Richtung.
|
||||
Aussage: Das System soll zu jedem Beleg sowohl dessen Ursprungsbelege als auch dessen Folgebelege ermittelbar machen und die Richtung der Beziehung (Ursprung vs. Folge) explizit kennzeichnen.
|
||||
Ergebnis: Eine Abfrage für einen Lieferschein liefert sowohl den auslösenden Auftrag (IsOrigin=1) als auch eine daraus erzeugte Rechnung (IsOrigin=0).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs:75-138 - Begründung: Konkrete SQL-Konstruktion mit `IsOrigin`-Spalte belegt die bidirektionale Modellierung.
|
||||
Prüfidee: Für einen Lieferschein mit bekanntem Ursprungsauftrag und bekannter Folgerechnung liefert `GetRelatedItemsForObject` genau diese zwei Objekte mit korrektem IsOrigin-Wert.
|
||||
Tracelinks: StRS-003; SwRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-004
|
||||
|
||||
```
|
||||
ID: SyRS-004
|
||||
Titel: Unterstützung externer Objektreferenzen in der Belegkette
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System, externes System (z. B. DocBee)
|
||||
Vorbedingung: Ein externes System hat einen Beleg (z. B. eine Bestellung) referenziert, ohne dass eine interne I3D bekannt ist.
|
||||
Fakt: `ReceiptProgressionBL` unterscheidet `CentronEntityReference` (interne I3D) und `ExternalObjectEntityReference` (externe Referenz-ID + -Typ) und pflegt eine eigene Tabelle `ObjectExternalReferences` zur Auflösung externer Referenzen auf interne Belege.
|
||||
Aussage: Das System soll Verknüpfungen zwischen internen Belegen und Objekten externer Systeme über eine generische Referenztabelle abbilden können, wenn keine interne ID vorliegt.
|
||||
Ergebnis: Ein extern referenziertes Objekt (z. B. "DocBee") lässt sich auf den zugehörigen internen Auftrag/Lieferschein auflösen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptProgressionBL.cs:117-138 (CreateExternalObjectRelatedItemsSql) - Begründung: Konkrete Abfrage auf Tabelle `ObjectExternalReferences` mit Kommentar "From Order -> DocBee and from DocBee -> DeliveryList" als Bestätigung des Anwendungsfalls.
|
||||
Prüfidee: Ein Datensatz in `ObjectExternalReferences` mit bekannter ExternalReferenceID liefert bei Abfrage den verknüpften internen Auftrag/Lieferschein.
|
||||
Tracelinks: StRS-003, StRS-004; SwRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-005
|
||||
|
||||
```
|
||||
ID: SyRS-005
|
||||
Titel: Eindeutiger, endlicher Belegstatus als Systemzustand
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: Ein Beleg wird angelegt, geändert oder storniert.
|
||||
Fakt: `ReceiptState` ist ein geschlossenes Enum mit genau drei Werten (Active/Completed/Canceled); es existiert keine weitere Zwischenstufe im Typsystem.
|
||||
Aussage: Das System soll den Belegstatus als endliche, geschlossene Zustandsmenge {offen, abgeschlossen, storniert} führen; jeder Beleg befindet sich zu jedem Zeitpunkt in genau einem dieser Zustände.
|
||||
Ergebnis: Es existiert kein undefinierter/vierter Belegstatus; jede Statusabfrage liefert einen der drei Werte.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Enum-Definition ist die durchgesetzte Typgrenze, kein anderer Wert ist im Code zuweisbar.
|
||||
Prüfidee: Statischer Test: Serialisierung/Deserialisierung eines Belegs erlaubt keinen anderen Enum-Wert als die drei definierten.
|
||||
Tracelinks: StRS-005; SwRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-006
|
||||
|
||||
```
|
||||
ID: SyRS-006
|
||||
Titel: Nebenläufigkeitssichere Nummernvergabe
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (Zuverlässigkeit, ISO 25010: Reliability/Fault Tolerance)
|
||||
Akteur: System
|
||||
Vorbedingung: Mehrere Benutzer speichern gleichzeitig neue Belege desselben Nummernkreises.
|
||||
Fakt: `NumberGroupBL.GetNextNumber` verwendet eine Wiederholschleife mit bedingtem Update (`Where(Current == alterWert).Set(Current, neuerWert)`); nur bei genau einer betroffenen Zeile (`rowCountChanged == 1`) gilt die Nummer als vergeben, sonst wird erneut ermittelt.
|
||||
Aussage: Das System soll bei gleichzeitiger Nummernvergabe durch mehrere Benutzer/Prozesse Kollisionen durch ein optimistisches Sperrverfahren mit automatischer Wiederholung verhindern.
|
||||
Ergebnis: Auch unter Nebenläufigkeit erhält jede Anfrage eine eindeutige Nummer; keine doppelte Vergabe, kein Deadlock durch das gewählte Verfahren.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs:62-92 - Begründung: Konkrete Implementierung des Compare-and-Swap-Musters via bedingtem UPDATE und Schleife.
|
||||
Prüfidee: Lasttest mit N parallelen Threads, die `GetNextNumber(updateDatabase:true)` für denselben Nummernkreis aufrufen: alle N Ergebnisse müssen paarweise verschieden sein.
|
||||
Tracelinks: StRS-006; SwRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-007
|
||||
|
||||
```
|
||||
ID: SyRS-007
|
||||
Titel: Änderungsprotokollierung an Verkaufsbelegen
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit (Nachvollziehbarkeit/Audit; ISO 25010: Security/Accountability)
|
||||
Akteur: System
|
||||
Vorbedingung: Ein Beleg wird angelegt, geändert oder ein belegbezogenes Ereignis tritt ein.
|
||||
Fakt: Die Entität `ReceiptLog` speichert je Ereignis Belegart (`ReceiptKind`), Beleg-I3D, Belegversion, Ereignisart (`ReceiptLogKind`), Freitextbeschreibung, Zeitstempel, Client-Version und den ausführenden Mitarbeiter (`EmployeeCompact`); `ReceiptLogBL.GetLogs` erlaubt gefilterte Abfrage.
|
||||
Aussage: Das System soll sicherheits- und nachvollziehbarkeitsrelevante Ereignisse an Verkaufsbelegen (wer, wann, was, mit welcher Version) revisionssicher protokollieren und abrufbar machen.
|
||||
Ergebnis: Zu jedem Beleg lässt sich eine chronologische, personenbezogene Ereignishistorie anzeigen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptLog.cs - Begründung: Persistente Entität mit Employee-, Zeitstempel- und Versionsfeldern belegt durchgesetzte Protokollierung auf Datenebene.
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptLogBL.cs (GetLogs) - Begründung: Bestätigt Abrufbarkeit der Historie als Programmfunktion.
|
||||
Prüfidee: Nach Änderung eines Belegs existiert ein neuer `ReceiptLog`-Eintrag mit korrektem Employee- und Zeitstempel-Wert.
|
||||
Tracelinks: StRS-003; SwRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Es ist nicht verifiziert, ob *jede* Änderung protokolliert wird oder nur bestimmte, im Code explizit ausgelöste Ereignisarten (`ReceiptLogKind`) — die konkrete Aufrufstellenliste wurde nicht vollständig erhoben.]
|
||||
```
|
||||
|
||||
## SyRS-008
|
||||
|
||||
```
|
||||
ID: SyRS-008
|
||||
Titel: Statusabhängige Zusatzautorisierung beim Ticketabschluss
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System, Support-Mitarbeiter
|
||||
Vorbedingung: Ein Ticket wird gespeichert und der Zielstatus entspricht dem konfigurierten "geschlossen"-Status.
|
||||
Fakt: `HelpdeskBL.CheckUserRigths` fragt den konfigurierten Abschluss-Status über `HelpdeskSettingsBL.GetClosedHelpdeskState()` ab (kein hartkodierter Enum-Wert) und verlangt nur in diesem Fall zusätzlich das Recht CLOSE_REQUEST; bei Verlassen des geschlossenen Status wird zudem `ClosedAt` zurückgesetzt.
|
||||
Aussage: Das System soll den für "geschlossen" geltenden Ticketstatus konfigurierbar halten und beim Übergang in bzw. aus diesem Status zusätzliche, statusspezifische Regeln (Rechteprüfung, Zeitstempel-Rücksetzung) automatisch anwenden.
|
||||
Ergebnis: Ein Statuswechsel in den konfigurierten Abschlussstatus ohne CLOSE_REQUEST-Recht wird abgelehnt; ein Statuswechsel aus dem Abschlussstatus heraus löscht automatisch das Abschlussdatum.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskBL.cs:428-443 - Begründung: Bedingte Logik direkt im Speicherpfad (DoBeforeSave→CheckRights→CheckUserRigths).
|
||||
Prüfidee: Statuswechsel eines Tickets vom konfigurierten Abschlussstatus zurück auf "in Bearbeitung" führt zu `ClosedAt == null` nach dem Speichern.
|
||||
Tracelinks: StRS-008; SwRS-009
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-009
|
||||
|
||||
```
|
||||
ID: SyRS-009
|
||||
Titel: Atomare Bestandsfortschreibung bei Belegbuchung
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System, Lagermitarbeiter
|
||||
Vorbedingung: Ein Beleg-Posten (z. B. Lieferscheinposition) mit Mengen- und ggf. Preisänderung wird gebucht.
|
||||
Fakt: `ArticleStockBL.UpdateArticlePurchasePrice` ermittelt den bisherigen Einkaufspreis aus `SecondaryStockArticle`, berechnet einen neuen Preis und ruft `UpdateArticlePurchasePriceThroughStockBooking` unter Übergabe von Beleg, Position, Lager, alter/neuer Menge und altem/neuem Preis auf.
|
||||
Aussage: Das System soll bei der Buchung eines Beleg-Postens Bestandsmenge und Einkaufspreisbewertung des betroffenen Artikels konsistent in einem Vorgang fortschreiben, unter Bezug auf den auslösenden Beleg.
|
||||
Ergebnis: Nach der Buchung spiegeln Bestandsmenge und -bewertung exakt die im Beleg erfassten Mengen-/Preisänderungen wider.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/StockManagement/ArticleStockBL.cs:74-148 - Begründung: Konkrete Methode mit Beleg-/Positions-/Lagerparametern belegt den durchgesetzten Zusammenhang zwischen Belegbuchung und Bestandsfortschreibung.
|
||||
Prüfidee: Buchung eines Lieferscheinpostens mit abweichendem Einkaufspreis führt zu aktualisiertem `SecondaryStockArticle`-Preis für den betroffenen Artikel/Lagerort.
|
||||
Tracelinks: StRS-009; SwRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-010
|
||||
|
||||
```
|
||||
ID: SyRS-010
|
||||
Titel: Partnerspezifische EDI-Importschnittstellen
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Externes System (EDI-Partner)
|
||||
Vorbedingung: Eine partnerspezifische Nachricht (Auftragsbestätigung, Rechnung) liegt in einem definierten Format vor.
|
||||
Fakt: Für jeden Partner existiert ein eigener Ordner/eine eigene Klassenstruktur unter `src/backend/Centron.BL/EDI/*`; für strukturierte E-Rechnungen zusätzlich ein eigener `Zugferd`-Ordner sowie ein `Opentrans21`-Ordner für das Standardformat openTRANS 2.1.
|
||||
Aussage: Das System soll für jeden unterstützten EDI-Partner eine eigene, partnerspezifische Importlogik bereitstellen und zusätzlich das Standardformat openTRANS 2.1 sowie ZUGFeRD/XRechnung unterstützen.
|
||||
Ergebnis: Eingehende partnerspezifische Nachrichten werden korrekt geparst und in interne Belege/Belegreferenzen überführt.
|
||||
Belege:
|
||||
- [PRIMÄR] Verzeichnisse src/backend/Centron.BL/EDI/{Alltron,ALSO,AlsoCH,Komsa,Concerto,EGIS,Opentrans21,Zugferd,SupplierEDI} - Begründung: Vorhandensein eigenständiger Klassenbäume je Partner/Format belegt implementierte, spezifische Verarbeitungslogik.
|
||||
Prüfidee: Für jeden Partnerordner existiert mindestens eine BL-Klasse mit Importmethode; Testnachricht des Partnerformats erzeugt einen validen internen Beleg.
|
||||
Tracelinks: StRS-010; SwRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Inhaltliche Details/Feldmappings je Partnerformat wurden nicht geprüft — nur die strukturelle Existenz der Module ist belegt.]
|
||||
```
|
||||
|
||||
## SyRS-011
|
||||
|
||||
```
|
||||
ID: SyRS-011
|
||||
Titel: Getrennte Authentifizierungsdomäne für Web-Accounts
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Kunde (Web-Benutzer), System
|
||||
Vorbedingung: Ein Web-Benutzer meldet sich am Portal CentronNexus an.
|
||||
Fakt: `AppRightsBL.CheckWebRightsFromUser` prüft Rechte über eine eigene Tabelle `WebAccountsRights`, getrennt von der internen `Sichtrus`/`Sichmemb`-Struktur für `AppUser`; `WebAccount.Password` wird ebenfalls separat mit SHA1 verglichen (`UsersBL.ChangeOwnPassword`).
|
||||
Aussage: Das System soll interne Mitarbeiterkonten (AppUser) und externe Kundenkonten (WebAccount) als getrennte Authentifizierungs- und Rechtedomänen mit eigenen Datenmodellen führen.
|
||||
Ergebnis: Ein Web-Account kann ausschließlich über WebAccountsRights-Zuweisungen autorisiert werden und niemals interne AppUser-Rechte erben.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs:113-130 (CheckWebRightsFromUser) - Begründung: Eigenständige SQL-Abfrage auf separater Tabelle, keine Überschneidung mit interner Rechteprüfung.
|
||||
Prüfidee: Ein WebAccount ohne explizite WebAccountsRights-Zuweisung erhält bei `CheckWebRightsFromUser` eine leere Ergebnisliste, selbst wenn ein gleichnamiges internes Recht existiert.
|
||||
Tracelinks: StRS-011; SwRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-012
|
||||
|
||||
```
|
||||
ID: SyRS-012
|
||||
Titel: Austauschbarkeit der Datenzugriffsart pro Modul (Übertragbarkeit)
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (ISO 25010: Portabilität/Adaptability)
|
||||
Akteur: System, Client (WPF-UI)
|
||||
Vorbedingung: Ein Modul wird sowohl im lokalen SQL-Server-Modus als auch im Webservice-Modus betrieben.
|
||||
Fakt: `ModuleRegistration`/`AppModuleController` deklariert je Modul unterstützte `CentronConnectionType`-Werte; `ClassContainer` registriert automatisch die passende `ILogic`-Implementierung (`BL*Logic` bzw. `WS*Logic`) nach Namenskonvention.
|
||||
Aussage: Das System soll es erlauben, ohne Änderung der aufrufenden ViewModel-Schicht zwischen direktem Datenbankzugriff und Webservice-Zugriff zu wechseln, sofern das jeweilige Modul die Verbindungsart deklariert unterstützt.
|
||||
Ergebnis: Ein als "CentronWebServices"-fähig deklariertes Modul funktioniert identisch, wenn der Client per Fernzugriff statt per lokaler DB-Verbindung betrieben wird.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/getting-started/general-structure.md (Abschnitt "Connection Type Support", "ClassContainer and ILogic Pattern") - Begründung: Repository-interne Architekturdokumentation beschreibt den durchgesetzten Registrierungsmechanismus konkret mit Codebeispiel.
|
||||
Prüfidee: Ein Modul mit `SupportsConnectionTypes = [SqlServer, CentronWebServices]` liefert bei beiden Verbindungsarten dieselben Testdaten für dieselbe Anfrage.
|
||||
Tracelinks: StRS-012; SwRS-011
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
## SyRS-013
|
||||
|
||||
```
|
||||
ID: SyRS-013
|
||||
Titel: Deutsch als verbindliche Standardsprache der Benutzeroberfläche
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (ISO 25010: Usability/Kompatibilität mit kultureller Erwartung)
|
||||
Akteur: System, alle Benutzer
|
||||
Vorbedingung: Eine neue benutzersichtbare Zeichenkette wird im System benötigt.
|
||||
Fakt: Lokalisierung erfolgt über `LocalizedStrings.resx` (Basis = Deutsch) und `LocalizedStrings.en.resx` (Englisch) als zusätzliche Sprache; die Dokumentation schreibt Deutsch als verpflichtende Basissprache fest.
|
||||
Aussage: Das System soll deutsche Zeichenketten als verbindliche Basissprache in allen Resource-Dateien führen; Englisch ist eine optionale Zusatzsprache.
|
||||
Ergebnis: Jede benutzersichtbare Zeichenkette ist mindestens auf Deutsch vorhanden; das Fehlen einer englischen Übersetzung führt zu keinem Systemfehler (Fallback auf Deutsch anzunehmen).
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md (Abschnitt "Language Requirements") - Begründung: Beschreibt Resource-Datei-Konvention und Fallback-Erwartung.
|
||||
Prüfidee: Für eine resx-Datei ohne .en.resx-Pendant liefert die Lokalisierung zur Laufzeit den deutschen Text statt eines Fehlers/leeren Strings.
|
||||
Tracelinks: StRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Das konkrete Fallback-Verhalten der Lokalisierungs-Infrastruktur bei fehlender Übersetzung wurde nicht im Code verifiziert, sondern nur aus der .resx-Konvention geschlossen.]
|
||||
```
|
||||
|
||||
## SyRS-014
|
||||
|
||||
```
|
||||
ID: SyRS-014
|
||||
Titel: Passwortspeicherung als Hashwert
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System, interner Benutzer, Web-Benutzer
|
||||
Vorbedingung: Ein Benutzer ändert oder validiert sein Passwort.
|
||||
Fakt: `UsersBL.ChangeOwnPassword`/`UpdatePassword` sowie `WebAccountBL` verwenden `SHA1Decoder.GetDecodedSHA1String`, welches Klartext-Passwörter mit SHA-1 (ohne erkennbares Salt) hasht und als Hex-String vergleicht/speichert.
|
||||
Aussage: Das System soll Passwörter niemals im Klartext speichern, sondern ausschließlich als Hashwert ablegen und Vergleiche ausschließlich über den Hashwert durchführen.
|
||||
Ergebnis: In der Datenbank ist zu keinem Zeitpunkt ein Klartextpasswort persistiert; jede Anmeldung/Änderung erfolgt über Hashvergleich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Common/TextCoding/SHA1Decoder.cs - Begründung: Durchgesetzte Implementierung, die Klartext nie persistiert, sondern nur den Hash zurückgibt.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/UsersBL.cs:56-114 - Begründung: Aufrufstelle zeigt konkrete Verwendung des Hashings im Passwortänderungs-Pfad.
|
||||
Prüfidee: Nach Passwortänderung enthält die Datenbankspalte `Password` einen 40-stelligen Hex-String, kein Klartext.
|
||||
Tracelinks: StRS-001; SwRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround - Begründung für Kennzeichnung: SHA-1 gilt kryptographisch als veraltet (keine adaptive Kostenfunktion, kein erkennbares Salting im untersuchten Code), was für eine Web-/SaaS-Neuimplementierung priorisiert zu überprüfen ist (siehe Analysebericht.md, Sicherheitsrisiken).
|
||||
```
|
||||
|
||||
## SyRS-015
|
||||
|
||||
```
|
||||
ID: SyRS-015
|
||||
Titel: Konfigurierbare Mindestlänge für Passwörter
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System, Administrator
|
||||
Vorbedingung: Ein Benutzer setzt ein neues Passwort.
|
||||
Fakt: `UsersBL.IsValidAppUserPassword` vergleicht die Länge des neuen Passworts gegen `appUser.PasswordMinLength` (pro Benutzer/Konfiguration hinterlegter Wert, > 0 aktiviert die Prüfung).
|
||||
Aussage: Das System soll eine konfigurierbare Mindestlänge für Passwörter durchsetzen, sofern für den jeweiligen Benutzer eine Mindestlänge > 0 hinterlegt ist.
|
||||
Ergebnis: Ein Passwortänderungsversuch, der die konfigurierte Mindestlänge unterschreitet, wird mit Fehlermeldung "Das Passwort ist zu kurz" abgelehnt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/UsersBL.cs:124-129 - Begründung: Durchgesetzte Prüfung unmittelbar vor dem Speichern des neuen Passworts.
|
||||
Prüfidee: Setzen eines Passworts mit Länge < PasswordMinLength liefert Result mit Status Error und der genannten Fehlermeldung.
|
||||
Tracelinks: SyRS-014; SwRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE: Es wurde nicht geprüft, ob weitere Komplexitätsregeln (Sonderzeichen, Ziffern, Historie) an anderer Stelle zusätzlich durchgesetzt werden — nur die Längenprüfung ist in UsersBL.cs belegt.]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Ende SyRS – 15 Anforderungen.*
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# Traceability-Tabelle
|
||||
|
||||
Konsolidierte Forward-/Backward-Traceability zwischen StRS, SyRS und SwRS, mit dem jeweils primären Artefaktbeleg (vollständige Beleglisten inkl. SEKUNDÄR/KONTEXT stehen in den jeweiligen `.md`-Dateien).
|
||||
|
||||
| StRS-ID | SyRS-ID | SwRS-ID | Primärer Artefaktbeleg |
|
||||
|---|---|---|---|
|
||||
| StRS-001 | SyRS-001 | SwRS-001 | `AppRightsBL.cs:95-111` (CheckRightsFromUser, SQL Sichtrus/Sichmemb) |
|
||||
| StRS-001 | SyRS-001 | SwRS-002 | `UserRightsExt.cs:18-32` (HasUserRight, fail-closed) |
|
||||
| StRS-002 | SyRS-002 | SwRS-003 | `HelpdeskBL.cs:245-291` (ShowHelpdeskRight-Ermittlung) |
|
||||
| StRS-003 | SyRS-003 | SwRS-004 | `ReceiptProgressionBL.cs:75-138` (GetRelatedItemsForObject, IsOrigin) |
|
||||
| StRS-003 | SyRS-004 | SwRS-005 | `ReceiptProgressionBL.cs:117-138` (ObjectExternalReferences) |
|
||||
| StRS-003 | SyRS-007 | — | `ReceiptLog.cs` (Audit-Log-Entität) |
|
||||
| StRS-004 | SyRS-004 | SwRS-005 | `ReceiptProgressionBL.cs:140-153` (DownPaymentForOrderI3D) |
|
||||
| StRS-005 | SyRS-005 | SwRS-006 | `ReceiptState.cs` (Enum Active/Completed/Canceled) |
|
||||
| StRS-006 | SyRS-006 | SwRS-007 | `NumberGroupBL.cs:62-135` (GetNextNumber, CAS-Update) |
|
||||
| StRS-007 | SyRS-007 | — | `ReceiptLog.cs`, `ReceiptLogBL.cs` (GetLogs) |
|
||||
| StRS-007 | SyRS-008 | SwRS-009 | `HelpdeskBL.cs:428-443` (CheckUserRigths, ClosedAt) |
|
||||
| StRS-008 | SyRS-008 | SwRS-009 | `HelpdeskBL.cs:433-439` (CLOSE_REQUEST-Prüfung) |
|
||||
| StRS-009 | SyRS-009 | SwRS-010 | `ArticleStockBL.cs:74-148` (UpdateArticlePurchasePrice) |
|
||||
| StRS-010 | SyRS-010 | SwRS-004 | Verzeichnis `src/backend/Centron.BL/EDI/*` |
|
||||
| StRS-011 | SyRS-011 | SwRS-012 | `AppRightsBL.cs:113-130` (CheckWebRightsFromUser, WebAccountsRights) |
|
||||
| StRS-012 | SyRS-012 | SwRS-011 | `docs/getting-started/general-structure.md` (ClassContainer/ILogic) |
|
||||
| StRS-013 | SyRS-013 | — *(Lücke, s. u.)* | `docs/getting-started/general-structure.md` (German-First Language Policy) |
|
||||
| StRS-014 | SyRS-007 | SwRS-008 [HYPOTHESE] | `CentronRights.md` Abschnitte 8/9 (kein PRIMÄR-Codebeleg) |
|
||||
| — *(kein direkter StRS-Parent, Sicherheitsverfeinerung von StRS-001)* | SyRS-014 | SwRS-013 | `SHA1Decoder.cs` (Passwort-Hashing) |
|
||||
| — *(Sicherheitsverfeinerung von SyRS-014)* | SyRS-015 | SwRS-013 | `UsersBL.cs:124-129` (PasswordMinLength) |
|
||||
|
||||
## Bekannte Lücken in der Traceability
|
||||
|
||||
- **StRS-013 → SwRS:** Für die Sprachanforderung existiert keine eigene SwRS-Anforderung, da in dieser Iteration keine konkrete Lokalisierungs-Infrastrukturklasse (Resource-Manager-Fallback-Logik) gelesen wurde. Als Nachschlagspunkt in `Analysebericht.md` vermerkt.
|
||||
- **SyRS-014/SyRS-015 ohne eigene StRS-ID:** Beide wurden aus StRS-001 ("Zugriffssteuerung") als technische Sicherheitsverfeinerung abgeleitet, ohne dass eine eigene, distinct formulierte Stakeholder-Anforderung zu Passwortregeln vorlag. Empfehlung für Folgeiteration: eigene StRS-Anforderung "Passwortsicherheitsrichtlinie" ergänzen, sobald weitere Evidenz (z. B. Komplexitätsregeln, Sperrverhalten nach Fehlversuchen) erhoben ist.
|
||||
- **Mehrfachverwendung von SwRS-004 und SwRS-005:** Beide SwRS-Anforderungen werden von mehreren StRS/SyRS-Anforderungen referenziert (n:m-Beziehung), da `ReceiptProgressionBL` mehrere fachliche Aussagen (Belegkette, Anzahlung, externe Referenzen, EDI-Objektbezug) mit derselben Komponente belegt. Dies ist beabsichtigt und kein Fehler.
|
||||
|
||||
## Konsistenzprüfung (siehe auch Analysebericht.md)
|
||||
|
||||
- Alle in dieser Tabelle referenzierten StRS-/SyRS-/SwRS-IDs existieren in den jeweiligen Dokumenten (manuell gegengeprüft, keine automatisierte ID-Extraktion verfügbar in dieser Iteration).
|
||||
- Keine doppelt vergebenen IDs festgestellt (IDs wurden fortlaufend und einmalig pro Dokument vergeben, StRS-001…014, SyRS-001…015, SwRS-001…013).
|
||||
- Ein Tracelink verweist auf einen SwRS-Eintrag, der selbst als vollständige `[HYPOTHESE]` markiert ist (SwRS-008, referenziert von StRS-014) — dies ist zulässig, da die Traceability den Zusammenhang dokumentiert, nicht dessen Bestätigungsstatus verändert.
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
# Messprotokoll - V1 (Baseline, solo) - Prompt-Version 01, Lauf 7 (Lauf A)
|
||||
|
||||
> **Erste echte V1-Messung.** Agentenmodus `solo`: Der Lauf durfte keine Subagenten starten.
|
||||
> Die Laeufe 1-6 liefen faktisch mit eingebauten Subagenten und gehoeren zu **V1b**.
|
||||
>
|
||||
> **Parallelbetrieb:** Dieser Lauf lief zeitgleich mit `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173143_v3.2.0-2bc6`.
|
||||
> Beide Laeufe konkurrierten um CPU, Netzwerk und API-Kontingent. **Wanduhrzeit, `duration_ms`
|
||||
> und `duration_api_ms` sind dadurch verzerrt** und nicht mit seriellen Laeufen vergleichbar.
|
||||
> Tokens, Kosten, Anforderungsanzahl und Denials sind unverzerrt.
|
||||
|
||||
## Lauf
|
||||
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
|
||||
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
|
||||
(identisch zu allen bisherigen Laeufen)
|
||||
- **Startzeit:** 2026-08-25T17:31:58.0726774+02:00
|
||||
- **Endzeit:** 2026-08-25T17:44:43.3414748+02:00
|
||||
- **Dauer gesamt:** 00:12:45 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:12:43 (`duration_ms`) - API: 00:12:17
|
||||
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
|
||||
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
|
||||
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Pruefung: 0 Treffer);
|
||||
Remote entkoppelt: **ja**
|
||||
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
|
||||
|
||||
## Werkzeugkonfiguration
|
||||
- **Laufverzeichnis-ID:** `v3.2.0-496c`
|
||||
- **Ablage:** `Iteration 1/claude-sonnet-5/solo/high/`
|
||||
- **Parallele Laeufe:** ja - `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173143_v3.2.0-2bc6`
|
||||
- **Skill-Version:** `3.2.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 ueber `--disallowedTools Task Agent Workflow`
|
||||
- **Effort:** `high` — **nicht zur Laufzeit gesetzt**, sondern aus der Sitzung geerbt und
|
||||
nachtraeglich aus dem Session-Transkript rekonstruiert (104 Nachrichten, durchgaengig `high`).
|
||||
`RawResult.json` enthaelt kein `effort`-Feld. Ab Skill-Version 3.4.0 wird der Wert per
|
||||
`--effort` explizit gesetzt.
|
||||
- **Modell:** `claude-sonnet-5` (vom Versuchsleiter vor dem Lauf gewaehlt); zusaetzlich
|
||||
`claude-haiku-4-5-20251001` fuer interne Hilfsaufrufe (4.192 Input-/19 Output-Tokens)
|
||||
- **Permission-Mode:** `acceptEdits`
|
||||
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Eintraegen
|
||||
(22 x `Bash(...)`, 11 x `PowerShell(...)`, 3 x Agentenwerkzeuge `Task`/`Agent`/`Workflow`)
|
||||
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
|
||||
zusaetzlich `--safe-mode` und `--strict-mcp-config`
|
||||
- **MCP-Server / Agentendateien:** keine - aus dem Snapshot entfernt, zusaetzlich `--safe-mode`
|
||||
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
|
||||
- **Fast-Mode:** aus
|
||||
|
||||
## Verbrauch
|
||||
|
||||
### Hauptagent (`usage`)
|
||||
| Messgroesse | Wert |
|
||||
|---|---|
|
||||
| Input-Tokens | 84 |
|
||||
| Output-Tokens | 70.730 (davon 10.470 Thinking-Tokens) |
|
||||
| Cache-Write-Tokens | 165.125 |
|
||||
| Cache-Read-Tokens | 4.117.705 |
|
||||
| Agent-Turns | 68 |
|
||||
|
||||
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
|
||||
| Messgroesse | `claude-sonnet-5` | `claude-haiku-4-5-20251001` | Summe |
|
||||
|---|---:|---:|---:|
|
||||
| Input-Tokens | 84 | 4.192 | 4.276 |
|
||||
| Output-Tokens | 70.730 | 19 | 70.749 |
|
||||
| Cache-Write-Tokens | 165.125 | 0 | 165.125 |
|
||||
| Cache-Read-Tokens | 4.117.705 | 0 | 4.117.705 |
|
||||
| Tokens gesamt | 4.353.644 | 4.211 | **4.357.855** |
|
||||
|
||||
**Tokens gesamt: 4.357.855** (Summe aus Input, Output, Cache-Write und Cache-Read ueber alle Modelle; `total_cost_usd` steht weiterhin in `RawResult.json`)
|
||||
|
||||
Ohne Subagenten sind Haupt- und Gesamtwerte fuer `claude-sonnet-5` identisch - anders als in
|
||||
allen V1b-Laeufen, wo sie um bis zu Faktor 21,6 auseinanderlagen.
|
||||
|
||||
## Ergebnis
|
||||
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
|
||||
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
|
||||
- **Session-ID:** `fd630f39-23b8-4d68-b996-086b232c145c`
|
||||
- **Permission-Denials:** **0** - auch keine auf `Task`/`Agent`/`Workflow` (siehe Anmerkung 1)
|
||||
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** - die Sperre hat gegriffen,
|
||||
der Lauf ist als V1-Messung gueltig
|
||||
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
|
||||
|
||||
| Datei | Groesse | Inhalt |
|
||||
|---|---:|---|
|
||||
| `StRS.md` | 23.489 B | 14 Anforderungen |
|
||||
| `SyRS.md` | 22.713 B | 15 Anforderungen |
|
||||
| `SwRS.md` | 21.924 B | 13 Anforderungen |
|
||||
| `Traceability.md` | 4.012 B | 19 Datenzeilen |
|
||||
| `Hypothesen.md` | 5.024 B | 10 Inline-Markierungen `[HYPOTHESE]` |
|
||||
| `Glossar.md` | 6.317 B | Domaenenbegriffe |
|
||||
| `Analysebericht.md` | 12.579 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
|
||||
|
||||
Summe: **42 Anforderungen** ueber drei Ebenen.
|
||||
- **Root unveraendert:** 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`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 14 | 33,3 % |
|
||||
| SyRS | 15 | 35,7 % |
|
||||
| SwRS | 13 | 31,0 % |
|
||||
| **Gesamt** | **42** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| Sicherheit | 13 | 31,0 % |
|
||||
| funktional | 10 | 23,8 % |
|
||||
| Daten | 9 | 21,4 % |
|
||||
| Schnittstelle | 5 | 11,9 % |
|
||||
| nicht-funktional | 1 | 2,4 % |
|
||||
| nicht-funktional (Zuverlässigkeit, ISO 25010: Reliability/Fault Tolerance) | 1 | 2,4 % |
|
||||
| Sicherheit (Nachvollziehbarkeit/Audit; ISO 25010: Security/Accountability) | 1 | 2,4 % |
|
||||
| nicht-funktional (ISO 25010: Portabilität/Adaptability) | 1 | 2,4 % |
|
||||
| nicht-funktional (ISO 25010: Usability/Kompatibilität mit kultureller Erwartung) | 1 | 2,4 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 57 |
|
||||
| davon `PRIMÄR` | 42 (73,7 %) |
|
||||
| davon `SEKUNDÄR` | 6 (10,5 %) |
|
||||
| davon `KONTEXT` | 9 (15,8 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 38 (90,5 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 31 | 73,8 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 11 | 26,2 % |
|
||||
| als Workaround vermerkt | 3 | 7,1 % |
|
||||
| Konsolidierungskandidaten | 5 | 11,9 % |
|
||||
| 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** (20 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 42 von 42 mit Tracelinks (100,0 %) |
|
||||
|
||||
## Vergleich V1 (solo) gegen V1b (builtin)
|
||||
|
||||
| Messgroesse | **Lauf A (V1)** | **Lauf B (V1)** | V1b: Lauf 4 | Lauf 3 | Lauf 6 | Lauf 5 |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| Subagenten | **0** | **0** | 0 | 7 | 7 | 14 |
|
||||
| Anforderungen | **42** | **82** | 55 | 106 | 189 | 325 |
|
||||
| Tokens gesamt | **4.357.855** | **12.598.503** | 27.562.244 | 11.516.200 | 32.568.122 | 52.713.542 |
|
||||
| Output-Tokens | **70.749** | **129.077** | 121.989 | 229.997 | 466.115 | 1.266.149 |
|
||||
| Cache-Read | **4,12 M** | **12,23 M** | 27,18 M | 10,54 M | 30,78 M | 44,83 M |
|
||||
| Agent-Turns | **68** | **107** | 147 | 69 | 29 | 31 |
|
||||
| Denials | **0** | **0** | 0 | 0 | 0 | 1 |
|
||||
|
||||
## Anmerkungen/Auffaelligkeiten
|
||||
|
||||
1. **Keine Denials auf die gesperrten Agentenwerkzeuge - entgegen der Erwartung.** Im Skill war
|
||||
vermerkt, dass im Solo-Modus Denials auf `Task`/`Agent`/`Workflow` "erwartbar" seien. Beide
|
||||
Laeufe zeigen **0**. Gesperrte Werkzeuge werden dem Modell offenbar gar nicht erst angeboten;
|
||||
es plant von vornherein eine Einzelkontext-Strategie, statt zu delegieren und abgewiesen zu
|
||||
werden. Die Bedingung wirkt also ueber die Planung, nicht ueber Fehlversuche - methodisch die
|
||||
sauberere Variante. Der `Workflow`-Denial im Verifikationstest kam nur zustande, weil der
|
||||
Testprompt ausdruecklich zum Delegieren aufforderte.
|
||||
|
||||
2. **V1 ist erheblich guenstiger als V1b.** 2,20 und 12.598.503 Tokens gegenueber 6,82 bis 52.713.542 Tokens.
|
||||
Selbst der teurere der beiden V1-Laeufe kostet weniger als der guenstigste V1b-Lauf. Ursache
|
||||
ist der fehlende Subagenten-Overhead: Ohne parallele Kontexte entfaellt das mehrfache Einlesen
|
||||
derselben Artefakte, sichtbar an den deutlich niedrigeren Cache-Read-Tokens.
|
||||
|
||||
3. **V1 liefert weniger Anforderungen - aber die Streuung bleibt.** 42 gegenueber 82 zwischen zwei
|
||||
Laeufen derselben Bedingung ist Faktor 2,0. Das ist geringer als die Faktor-5,9-Streuung in
|
||||
V1b, aber immer noch zu gross, um aus zwei Messpunkten eine belastbare Aussage abzuleiten.
|
||||
Fuer eine Aussage "V1 liefert weniger als V1b" waeren mehr Laeufe je Bedingung noetig.
|
||||
|
||||
4. **Parallelbetrieb technisch fehlerfrei.** Beide Laeufe schrieben in getrennte Verzeichnisse mit
|
||||
eigenem `_meta` (eigene `before.txt`, eigener archivierter Prompt, eigene Zeitstempel). Keine
|
||||
Kollision, keine gegenseitige Ueberschreibung, beide Ergebnisverzeichnisse frei von
|
||||
Fremddateien, Root unveraendert. Das mit Skill-Version 3.1.0 eingefuehrte Verfahren
|
||||
funktioniert im Realbetrieb.
|
||||
|
||||
5. **Zeitangaben nicht fuer Laufzeitvergleiche verwenden.** Beide Laeufe konkurrierten um dieselbe
|
||||
Maschine. Lauf A brauchte 12:45, Lauf B 23:53 - der Unterschied ist nicht ohne Weiteres
|
||||
inhaltlich zu deuten, weil Lauf A frueher fertig war und Lauf B danach die Maschine allein
|
||||
hatte. Fuer Laufzeitvergleiche seriell messen.
|
||||
|
||||
6. **Manuelle Eingriffe waehrend des Laufs:** keine.
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"is_error":false,"duration_api_ms":737235,"num_turns":68,"stop_reason":"end_turn","session_id":"fd630f39-23b8-4d68-b996-086b232c145c","total_cost_usd":2.195796,"usage":{"input_tokens":84,"cache_creation_input_tokens":165125,"cache_read_input_tokens":4117705,"output_tokens":70730,"output_tokens_details":{"thinking_tokens":10470},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":165125,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":630,"cache_read_input_tokens":164371,"cache_creation_input_tokens":754,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":754},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":19,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004287,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-sonnet-5":{"inputTokens":84,"outputTokens":70730,"cacheReadInputTokens":4117705,"cacheCreationInputTokens":165125,"webSearchRequests":0,"costUSD":2.191509,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-sonnet-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":"All seven deliverables are written to the output directory. Summary of this run:\n\n- **Scope reality check**: The codebase has 16,063 `.cs` files across 93 top-level BL modules — far beyond what one iteration can cover at full depth. I prioritized 6 business-critical domains (rights/security, sales receipts/billing chain, helpdesk ticketing, authentication, document numbering, stock booking) selected by security/billing sensitivity and Git change-frequency, and documented this selection explicitly rather than superficially skimming everything.\n- **42 requirements** produced (14 StRS / 15 SyRS / 13 SwRS), every one carrying at least one concrete artifact reference (file path + line numbers, SQL, table/column names). Security- and billing-critical ones (rights checks, password hashing, ticket-close authorization, receipt numbering) all have a PRIMÄR code-level source.\n- **1 requirement fully flagged `[HYPOTHESE]`** (SwRS-008, timer-billing lock) because only documentation, not code, backed it — per the stricter evidence bar for billing logic.\n- **2 findings marked `belegt; Workaround`**: unsalted SHA-1 password hashing, and hardcoded numeric SQL literals duplicating an enum — both flagged as migration risks for the future Web/SaaS system.\n- **Consistency check** run and documented: no duplicate IDs, no unbacked requirements, no dangling tracelinks (verified via automated grep/comm, not just asserted).\n- `Analysebericht.md` names ~85 of 93 BL modules as not analyzed this round and lists 8 concrete follow-up priorities (payments/bookkeeping, 2FA/Entra ID login, stock valuation formula, CentronNexus portal, REST controllers, etc.) for the next iteration.\n\nThe source codebase itself was only read, never modified.","ttft_ms":3236,"ttft_stream_ms":1344,"time_to_request_ms":34,"type":"result","duration_ms":763350,"uuid":"c65373ca-671b-4634-bc18-3bd68ea630c6","queued_turn_count":0}
|
||||
+731
@@ -0,0 +1,731 @@
|
||||
[
|
||||
{
|
||||
"id": "StRS-001",
|
||||
"ebene": "StRS",
|
||||
"titel": "Rollenbasierte, feingranulare Zugriffssteuerung",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-001, SwRS-001, SwRS-002",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Einem Testbenutzer wird eine Gruppe ohne ein bestimmtes Recht zugewiesen; die zugehörige Funktion darf im Client nicht sichtbar/ausführbar sein.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-002",
|
||||
"ebene": "StRS",
|
||||
"titel": "Einschränkung von Rechten auf organisatorische Zuständigkeit (Filiale/Eigene Datensätze)",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-002, SwRS-003",
|
||||
"konsolidierung": "Kandidat: Gleiches Muster wiederkehrend bei Kalender (RIGHT_KALENDERANZEIGENEIGENE) und Mitarbeiterauslastung (RIGHT_MITARBEITERAUSLASTUNGNUREIGENEFILIALE) — im Zielsystem als generisches \"Sichtbarkeits-Scoping\" konsolidierbar.",
|
||||
"pruefidee": "Zwei Testbenutzer unterschiedlicher Filialen mit \"nur eigene Filiale\"-Recht dürfen jeweils nur Tickets ihrer eigenen Filiale in der Liste sehen.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-003",
|
||||
"ebene": "StRS",
|
||||
"titel": "Durchgängiger Verkaufsbelegprozess (Angebot bis Rechnung)",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-003, SyRS-004, SwRS-004, SwRS-005",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Aus einem Auftrag wird ein Lieferschein und daraus eine Rechnung erzeugt; `GetRelatedItemsForObject` für die Rechnung muss Auftrag und Lieferschein als Ursprungsbelege zurückliefern.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-004",
|
||||
"ebene": "StRS",
|
||||
"titel": "Anzahlungsrechnungen vor Auftragsabschluss",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-004, SwRS-005",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für einen Auftrag mit einer Anzahlungsrechnung liefert `GetRelatedItemsForObject(Auftrag)` die Anzahlungsrechnung als verknüpftes Objekt.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-005",
|
||||
"ebene": "StRS",
|
||||
"titel": "Nachvollziehbarer Lebenszyklus jedes Verkaufsbelegs",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-005, SwRS-006",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein neu angelegter Beleg hat Status \"offen\"; nach Stornierung liefert eine Statusabfrage \"storniert\".",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-006",
|
||||
"ebene": "StRS",
|
||||
"titel": "Eindeutige, lückenfreie Belegnummerierung je Mandant/Filiale",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-006, SwRS-007",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Zwei parallele Aufrufe von `GetNextNumber(updateDatabase:true)` für denselben Nummernkreis dürfen keine identische Nummer liefern (Lasttest mit paralleler Ausführung).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-007",
|
||||
"ebene": "StRS",
|
||||
"titel": "Ticket-/Vorgangsverwaltung im Kundenservice (Helpdesk)",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-007, SyRS-008, SwRS-008, SwRS-009",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein Ticket wird angelegt, bearbeitet, Zeit erfasst und abgeschlossen; jeder Schritt ist im Änderungsprotokoll nachvollziehbar.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-008",
|
||||
"ebene": "StRS",
|
||||
"titel": "Autorisierungspflicht für Ticketabschluss",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-002, SwRS-009",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Testbenutzer mit EDIT_HELPDESK aber ohne CLOSE_REQUEST versucht, Status auf \"geschlossen\" zu setzen → erwartet: Fehler-Result, kein Speichern.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-009",
|
||||
"ebene": "StRS",
|
||||
"titel": "Bestandsführung für Artikel je Lagerort",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-009, SwRS-010",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Wareneingang über einen Lieferschein erhöht den Bestand des betroffenen Artikels am betroffenen Lagerort um die Liefermenge.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-010",
|
||||
"ebene": "StRS",
|
||||
"titel": "Elektronischer Datenaustausch mit Lieferanten (EDI)",
|
||||
"typ": "Schnittstelle",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT",
|
||||
"SEKUNDÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-010",
|
||||
"konsolidierung": "Kandidat: Partnerspezifische EDI-Module folgen strukturell ähnlichem Muster (Import/Connector-Klassen) — im Zielsystem als generisches EDI-Adapter-Framework konsolidierbar. [HYPOTHESE: nicht im Detail verglichen, ob die Partner-Implementierungen tatsächlich strukturell identisch sind — Bestätigung erfordert Tiefenanalyse je Partnermodul.]",
|
||||
"pruefidee": "Eine Testdatei im jeweiligen Partnerformat wird importiert; Ergebnis ist ein systemseitig referenzierbarer Beleg/Belegstatus.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-011",
|
||||
"ebene": "StRS",
|
||||
"titel": "Web-Portal als Zugang für Kunden und Mitarbeiter (CentronNexus)",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-011, SyRS-002",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein Web-Account meldet sich in CentronNexus an und sieht ausschließlich für ihn freigegebene Artikel (Sonderpreise) im WebCart.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-012",
|
||||
"ebene": "StRS",
|
||||
"titel": "Duale API-Erreichbarkeit (Web Service und Direktverbindung)",
|
||||
"typ": "Schnittstelle",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-012, SwRS-011",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für ein beliebiges Modul existieren sowohl eine `BL{Modul}Logic`- als auch eine `WS{Modul}Logic`-Klasse, die dasselbe `I{Modul}Logic`-Interface implementieren.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-013",
|
||||
"ebene": "StRS",
|
||||
"titel": "Deutschsprachige Benutzerführung als Marktanforderung",
|
||||
"typ": "nicht-funktional",
|
||||
"belege": [
|
||||
"SEKUNDÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-013",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Stichprobe von 20 zufälligen benutzersichtbaren Strings im WPF-Client: alle sind auf Deutsch vorhanden (Basis-resx).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "StRS-014",
|
||||
"ebene": "StRS",
|
||||
"titel": "Zeiterfassung als Abrechnungsgrundlage im Kundenservice",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: konkrete Sperrbedingung \"ist Teil eines Belegs\" wurde nur aus CentronRights.md übernommen, nicht im Code von HelpdeskBL.cs verifiziert — Bestätigung erfordert Analyse der Timer-BL-Klassen.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-007, SwRS-008",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Eine bereits abgerechnete Zeitbuchung eines Tickets kann über EDIT_TIME nicht mehr gelöscht werden (erwarteter Fehler).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-001",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Serverseitige Rechteprüfung gegen Gruppenmitgliedschaft",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-001; SwRS-001",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Direkter Aufruf von `CheckRightsFromUser` mit der I3D eines Rechts, das keiner Gruppe des Benutzers zugewiesen ist, liefert eine leere Liste.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-002",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Sichtbarkeits-Scoping von Datensätzen anhand einschränkender Rechte",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-002; SwRS-003",
|
||||
"konsolidierung": "Kandidat: identisches Scoping-Muster (All/OnlyOwn/OnlyOwnBranch) potenziell in weiteren Modulen (Kalender, Mitarbeiterauslastung) — nur für Helpdesk verifiziert, für andere Module [HYPOTHESE].",
|
||||
"pruefidee": "Benutzer mit SHOW_HELPDESK_ONLY_OWN_BRANCH erhält bei Ticketsuche ausschließlich Tickets seiner Filiale, auch bei explizitem Filterversuch auf andere Filialen.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-003",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Bidirektionale Belegverknüpfung (Ursprung/Folge) über Objektreferenzen",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-003; SwRS-004",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für einen Lieferschein mit bekanntem Ursprungsauftrag und bekannter Folgerechnung liefert `GetRelatedItemsForObject` genau diese zwei Objekte mit korrektem IsOrigin-Wert.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-004",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Unterstützung externer Objektreferenzen in der Belegkette",
|
||||
"typ": "Schnittstelle",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-003, StRS-004; SwRS-005",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein Datensatz in `ObjectExternalReferences` mit bekannter ExternalReferenceID liefert bei Abfrage den verknüpften internen Auftrag/Lieferschein.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-005",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Eindeutiger, endlicher Belegstatus als Systemzustand",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-005; SwRS-006",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Statischer Test: Serialisierung/Deserialisierung eines Belegs erlaubt keinen anderen Enum-Wert als die drei definierten.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-006",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Nebenläufigkeitssichere Nummernvergabe",
|
||||
"typ": "nicht-funktional (Zuverlässigkeit, ISO 25010: Reliability/Fault Tolerance)",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-006; SwRS-007",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Lasttest mit N parallelen Threads, die `GetNextNumber(updateDatabase:true)` für denselben Nummernkreis aufrufen: alle N Ergebnisse müssen paarweise verschieden sein.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-007",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Änderungsprotokollierung an Verkaufsbelegen",
|
||||
"typ": "Sicherheit (Nachvollziehbarkeit/Audit; ISO 25010: Security/Accountability)",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"SEKUNDÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Es ist nicht verifiziert, ob *jede* Änderung protokolliert wird oder nur bestimmte, im Code explizit ausgelöste Ereignisarten (`ReceiptLogKind`) — die konkrete Aufrufstellenliste wurde nicht vollständig erhoben.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-003; SwRS-004",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Nach Änderung eines Belegs existiert ein neuer `ReceiptLog`-Eintrag mit korrektem Employee- und Zeitstempel-Wert.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-008",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Statusabhängige Zusatzautorisierung beim Ticketabschluss",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-008; SwRS-009",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Statuswechsel eines Tickets vom konfigurierten Abschlussstatus zurück auf \"in Bearbeitung\" führt zu `ClosedAt == null` nach dem Speichern.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-009",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Atomare Bestandsfortschreibung bei Belegbuchung",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-009; SwRS-010",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Buchung eines Lieferscheinpostens mit abweichendem Einkaufspreis führt zu aktualisiertem `SecondaryStockArticle`-Preis für den betroffenen Artikel/Lagerort.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-010",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Partnerspezifische EDI-Importschnittstellen",
|
||||
"typ": "Schnittstelle",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Inhaltliche Details/Feldmappings je Partnerformat wurden nicht geprüft — nur die strukturelle Existenz der Module ist belegt.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-010; SwRS-004",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für jeden Partnerordner existiert mindestens eine BL-Klasse mit Importmethode; Testnachricht des Partnerformats erzeugt einen validen internen Beleg.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-011",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Getrennte Authentifizierungsdomäne für Web-Accounts",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-011; SwRS-012",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein WebAccount ohne explizite WebAccountsRights-Zuweisung erhält bei `CheckWebRightsFromUser` eine leere Ergebnisliste, selbst wenn ein gleichnamiges internes Recht existiert.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-012",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Austauschbarkeit der Datenzugriffsart pro Modul (Übertragbarkeit)",
|
||||
"typ": "nicht-funktional (ISO 25010: Portabilität/Adaptability)",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-012; SwRS-011",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ein Modul mit `SupportsConnectionTypes = [SqlServer, CentronWebServices]` liefert bei beiden Verbindungsarten dieselben Testdaten für dieselbe Anfrage.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-013",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Deutsch als verbindliche Standardsprache der Benutzeroberfläche",
|
||||
"typ": "nicht-funktional (ISO 25010: Usability/Kompatibilität mit kultureller Erwartung)",
|
||||
"belege": [
|
||||
"SEKUNDÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Das konkrete Fallback-Verhalten der Lokalisierungs-Infrastruktur bei fehlender Übersetzung wurde nicht im Code verifiziert, sondern nur aus der .resx-Konvention geschlossen.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-013",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für eine resx-Datei ohne .en.resx-Pendant liefert die Lokalisierung zur Laufzeit den deutschen Text statt eines Fehlers/leeren Strings.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-014",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Passwortspeicherung als Hashwert",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; Workaround - Begründung für Kennzeichnung: SHA-1 gilt kryptographisch als veraltet (keine adaptive Kostenfunktion, kein erkennbares Salting im untersuchten Code), was für eine Web-/SaaS-Neuimplementierung priorisiert zu überprüfen ist (siehe Analysebericht.md, Sicherheitsrisiken).",
|
||||
"hypothese": false,
|
||||
"workaround": true,
|
||||
"tracelinks": "StRS-001; SwRS-013",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Nach Passwortänderung enthält die Datenbankspalte `Password` einen 40-stelligen Hex-String, kein Klartext.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SyRS-015",
|
||||
"ebene": "SyRS",
|
||||
"titel": "Konfigurierbare Mindestlänge für Passwörter",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Es wurde nicht geprüft, ob weitere Komplexitätsregeln (Sonderzeichen, Ziffern, Historie) an anderer Stelle zusätzlich durchgesetzt werden — nur die Längenprüfung ist in UsersBL.cs belegt.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-014; SwRS-013",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Setzen eines Passworts mit Länge < PasswordMinLength liefert Result mit Status Error und der genannten Fehlermeldung.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-001",
|
||||
"ebene": "SwRS",
|
||||
"titel": "SQL-Join-Implementierung der Rechteprüfung",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"SEKUNDÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-001",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Unit-Test ruft CheckRightsFromUser mit einer Mischung aus zugewiesenen/nicht zugewiesenen Recht-IDs auf; Ergebnisliste enthält exakt die zugewiesene Teilmenge.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-002",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Fail-Closed-Verhalten bei Rechteprüfungsfehlern",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Das verschluckte Fehlerverhalten kann Diagnoseprobleme verursachen (falsche \"keine Berechtigung\"-Meldungen bei reinen Infrastrukturfehlern) — ob dies protokolliert wird, ist im gesichteten Code nicht erkennbar (kein Logging-Aufruf im catch-Block sichtbar).]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-001",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Simulation einer Exception innerhalb der Session-Erzeugung während `HasUserRight`-Aufruf: Rückgabewert ist `false`, keine Exception propagiert zum Aufrufer.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-003",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Vierwertige Sichtbarkeitsklassifikation im Helpdesk",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Die genaue Bedingung für `OnlyOwnAndNotify` (Zeilen vor 255) wurde nicht vollständig gelesen/zitiert — Herkunft und Zweck dieses vierten Modus benötigt weitere Codeanalyse.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-002",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für alle 2^3 Kombinationen der drei Basisrechte liefert die Methode den in der Tabelle der Fallunterscheidung dokumentierten Modus.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-004",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Objektart-Enum als Diskriminator für Belegtypen (CentronObjectKindNumeric)",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; Workaround - Begründung: Hartkodierte numerische Literale in SQL-Strings (statt Verweis auf das Enum selbst, z. B. `(int)CentronObjectKindNumeric.X`) sind an mehreren Stellen erkennbar (z. B. `2 AS ObjectKind` ohne Cast) und bergen ein Inkonsistenzrisiko bei künftigen Enum-Änderungen.",
|
||||
"hypothese": false,
|
||||
"workaround": true,
|
||||
"tracelinks": "SyRS-003, SyRS-004, SyRS-010",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Für jeden in ReceiptProgressionBL verwendeten numerischen Code existiert ein korrespondierender, namentlich passender Enum-Wert in `CentronObjectKindNumeric` (Konsistenzprüfung Enum vs. SQL-Literale).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-005",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Datenmodell der Anzahlungsrechnung",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-003, SyRS-004",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Rechnung mit gesetztem `DownPaymentForOrderI3D` erscheint bei Abfrage der verknüpften Objekte des referenzierten Auftrags.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-006",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Enum-zu-UI-Text-Zuordnung für Belegstatus",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-005",
|
||||
"konsolidierung": "Kandidat: Zwei redundante Zuordnungen (Attribut + switch-Methode) für dieselbe Information — im Zielsystem auf eine einzige Quelle konsolidierbar.",
|
||||
"pruefidee": "Für jeden Enum-Wert liefern sowohl das Description-Attribut als auch `GetReceiptStateString()` denselben deutschen Text (Konsistenzprüfung der doppelten Definition).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-007",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Compare-and-Swap-Update für Nummernkreis-Zähler",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR",
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-006",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Zwei parallele Transaktionen mit demselben Ausgangswert `Current`: nur eine darf erfolgreich committen, die andere muss die Schleife erneut durchlaufen und einen anderen Wert erhalten.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-008",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Sperrung der Zeiterfassungsänderung nach Abrechnung [HYPOTHESE]",
|
||||
"typ": "funktional",
|
||||
"belege": [
|
||||
"KONTEXT"
|
||||
],
|
||||
"status": "HYPOTHESE - Begründung für fehlende Bestätigung: Die konkrete Timer-BL-Implementierungsklasse wurde in dieser Iteration nicht identifiziert/gelesen; nur die Dokumentationsaussage liegt vor. Sicherheits-/Abrechnungsrelevanz erfordert laut Auftrag mindestens einen PRIMÄR-Beleg, der hier fehlt.",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "StRS-014",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Suche nach der konkreten Prüfmethode (voraussichtlich in einer `HelpdeskTimer*BL`-Klasse) und Verifikation der Bedingung im Code als Folgeschritt.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-009",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Statusgesteuerte Zeitstempel-Rücksetzung (ClosedAt)",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-008",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Ticket im Abschlussstatus mit gesetztem ClosedAt wird auf \"in Bearbeitung\" umgestellt → nach Speichern ist ClosedAt == null.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-010",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Verkettung von Mengen- und Preisfortschreibung bei Wareneingang",
|
||||
"typ": "Daten",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Die genaue Bewertungsformel (gleitender Durchschnitt vs. FIFO vs. letzter Einstandspreis) wird in `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` festgelegt, welches in dieser Iteration nicht gelesen wurde.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-009",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Zwei aufeinanderfolgende Wareneingänge mit unterschiedlichem Einkaufspreis führen zu einem im Artikel/Lagerort konsistent nachvollziehbaren, aktualisierten Preis (z. B. gleitender Durchschnitt oder letzter Preis – exakte Bewertungsmethode nicht Teil dieses Belegs).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-011",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Namenskonventionsbasierte Auto-Registrierung von Logic-Implementierungen",
|
||||
"typ": "Schnittstelle",
|
||||
"belege": [
|
||||
"SEKUNDÄR"
|
||||
],
|
||||
"status": "belegt; [HYPOTHESE: Die genaue Auto-Registrierungsimplementierung (Reflection-Scan, Konventionsprüfung, Fehlerverhalten bei Namensabweichung) wurde nicht im Quellcode von ClassContainer selbst verifiziert, sondern nur aus der Dokumentation übernommen.]",
|
||||
"hypothese": true,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-012",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Neues Test-Modul mit korrektem Namensschema wird ohne expliziten Registrierungsaufruf über `ClassContainer.Instance.WithInstance<I...Logic>()` auflösbar.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-012",
|
||||
"ebene": "SwRS",
|
||||
"titel": "Separates Rechte-Datenmodell für Web-Accounts",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt",
|
||||
"hypothese": false,
|
||||
"workaround": false,
|
||||
"tracelinks": "SyRS-011",
|
||||
"konsolidierung": "Kandidat: Zwei parallele, strukturell unterschiedliche Rechtemodelle (gruppenbasiert für AppUser, direkt für WebAccount) — im Zielsystem ggf. auf ein einheitliches RBAC-Modell konsolidierbar.",
|
||||
"pruefidee": "Datenmodellprüfung: `WebAccountsRights` besitzt keine Fremdschlüsselspalte auf eine Gruppentabelle (Strukturvergleich mit `Sichtrus`/`Sichmemb`).",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
},
|
||||
{
|
||||
"id": "SwRS-013",
|
||||
"ebene": "SwRS",
|
||||
"titel": "SHA-1-basierte Passwort-Hash-Funktion mit fester Kodierung",
|
||||
"typ": "Sicherheit",
|
||||
"belege": [
|
||||
"PRIMÄR"
|
||||
],
|
||||
"status": "belegt; Workaround - Begründung: Deterministisches, unsalted SHA-1-Hashing ist nach heutigem Stand der Technik nicht mehr empfohlen (Rainbow-Table-Anfälligkeit, fehlende adaptive Kostenfunktion); für die Web-/SaaS-Neuimplementierung priorisiert zu prüfen.",
|
||||
"hypothese": false,
|
||||
"workaround": true,
|
||||
"tracelinks": "SyRS-014",
|
||||
"konsolidierung": "nein",
|
||||
"pruefidee": "Zwei AppUser-Datensätze mit demselben Testpasswort erzeugen identische Werte in der Spalte `Password`.",
|
||||
"qm": "",
|
||||
"uebernahme": ""
|
||||
}
|
||||
]
|
||||
+64
@@ -0,0 +1,64 @@
|
||||
## Gefundene Anforderungen
|
||||
|
||||
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 14 | 33,3 % |
|
||||
| SyRS | 15 | 35,7 % |
|
||||
| SwRS | 13 | 31,0 % |
|
||||
| **Gesamt** | **42** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| Sicherheit | 13 | 31,0 % |
|
||||
| funktional | 10 | 23,8 % |
|
||||
| Daten | 9 | 21,4 % |
|
||||
| Schnittstelle | 5 | 11,9 % |
|
||||
| nicht-funktional | 1 | 2,4 % |
|
||||
| nicht-funktional (Zuverlässigkeit, ISO 25010: Reliability/Fault Tolerance) | 1 | 2,4 % |
|
||||
| Sicherheit (Nachvollziehbarkeit/Audit; ISO 25010: Security/Accountability) | 1 | 2,4 % |
|
||||
| nicht-funktional (ISO 25010: Portabilität/Adaptability) | 1 | 2,4 % |
|
||||
| nicht-funktional (ISO 25010: Usability/Kompatibilität mit kultureller Erwartung) | 1 | 2,4 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 57 |
|
||||
| davon `PRIMÄR` | 42 (73,7 %) |
|
||||
| davon `SEKUNDÄR` | 6 (10,5 %) |
|
||||
| davon `KONTEXT` | 9 (15,8 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 38 (90,5 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 31 | 73,8 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 11 | 26,2 % |
|
||||
| als Workaround vermerkt | 3 | 7,1 % |
|
||||
| Konsolidierungskandidaten | 5 | 11,9 % |
|
||||
| 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** (20 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 42 von 42 mit Tracelinks (100,0 %) |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+132
@@ -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_173142_sonnet5_solo_v3.2.0-496c\Ergebnisse\`.
|
||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T17:44:43.3414748+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T17:31:58.0726774+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# Subagenten-Aufrufe
|
||||
|
||||
Session `fd630f39-23b8-4d68-b996-086b232c145c`, Transkript `fd630f39-23b8-4d68-b996-086b232c145c.jsonl`.
|
||||
|
||||
`subagent_stats`: **0** Subagenten gesamt, davon **0** von Subagenten gestartet (max_depth 0). Direkt vom Hauptagenten erwartet: **0**. Im Transkript gefunden: **0**.
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
# Analysebericht
|
||||
|
||||
Reverse Requirements Engineering der Codebasis "CentronERP" (c-entron ERP-Suite). Dieser Bericht dokumentiert Vorgehen, Abdeckung, Konsistenzcheck und Selbstbewertung gemäß Auftrag.
|
||||
|
||||
## 1. Ausgangslage und Größenordnung
|
||||
|
||||
Die Codebasis umfasst laut Zählung zu Beginn der Analyse:
|
||||
|
||||
- **15.554** C#-Dateien und **1.233** XAML-Dateien unter `src/`
|
||||
- Backend-Fachlogik (`Centron.BL`): **~87** thematische Modulordner, davon die größten: Administration (959 Dateien), WebServices (464), Sales (248)
|
||||
- Entitätsschicht (`Centron.Entities/Entities`): **~80** thematische Unterordner, **1.179** Entitätsklassen allein direkt darunter
|
||||
- WPF-Desktopclient (`Centron.WPF.UI/Modules`): **30** Fachmodule
|
||||
- Separate Blazor-Webanwendung `CentronNexus`: **460** .razor-Dateien, **830** .cs-Dateien
|
||||
- REST-API-Controller (`Centron.Controllers/Controllers/v1`): **17** Bereichsordner (Accounts, Customers, Offers, Orders, Receipts, Tickets, Helpdesks, Contracts, DataExchange, Integrations, SelfCare, WebAccount, WebVersion, Nexoware, Administration, ...)
|
||||
- Weitere Backend-Bibliotheken: `Centron.DAO`, `Centron.Common`, `Centron.Gateway`, `Centron.Interfaces`, `Centron.Core`
|
||||
- Externe API-Integrationsprojekte (`src/apis`): 8 Projekte (CopDataAccess, EgisDataAccess, FinAPI, ITscopeDataAccess, IcecatDataAccess, EbInterface, Gls, Shipcloud)
|
||||
- Deployment/Infrastruktur: Docker-Compose-Umgebungen, WixSharp-Installer, Azure-Pipelines
|
||||
- Tests: separate Projekte für End-to-End-, Integrations- und Unit-Tests (`tests/`)
|
||||
|
||||
Eine erschöpfende Analyse dieser Gesamtmenge war im Rahmen einer einzelnen Iteration nicht möglich. Es wurde daher – wie im Auftrag vorgesehen – die Analysetiefe selbstständig priorisiert; dieser Bericht macht die Priorisierung und ihre Grenzen vollständig transparent.
|
||||
|
||||
## 2. Priorisierungsentscheidung
|
||||
|
||||
Priorisiert für **Tiefenanalyse** wurden Bereiche mit hoher fachlicher Kritikalität gemäß Auftrag (Sicherheit, Abrechnung/Fakturierung, Berechtigungen) sowie Bereiche mit erkennbar hoher Änderungsaktivität (jüngste Commits) und hoher strategischer Relevanz für eine Web-/SaaS-Neuimplementierung:
|
||||
|
||||
1. Rechte-/Berechtigungsmodell (`AppRightsBL`, Autorisierungs-Attribute der API)
|
||||
2. Belegwesen/Sales (`ReceiptBL`, `ReceiptBase`, Belegstatus, Belegkette)
|
||||
3. Belegnummernvergabe (`NumberGroupBL`)
|
||||
4. Zahlungsstatus-Verwaltung
|
||||
5. DSGVO/Datenschutz (`DataSecurityBL`, `DsgvoBL`)
|
||||
6. Digitale Signatur (`PdfSigningBL`, CentronNexus DocumentSigning)
|
||||
7. Web-Angebote/Kundenportal (CentronNexus WebOffer, Branding)
|
||||
8. Ticketing/Helpdesk (Datenmodell)
|
||||
9. Zeit-/Timer-Fakturierung
|
||||
10. Lagerbestand/Einkaufspreisführung (`ArticleBL`, Auszug)
|
||||
11. Authentifizierung/Autorisierung der zentralen API (`Centron.Host`, JWT/Ticket/SecretKey/Lizenz)
|
||||
12. Lizenz-/Modulmodell (`LicenseGuids`)
|
||||
13. Deployment/Containerisierung (Dockerfiles) als Grundlage für NFR-Aussagen
|
||||
|
||||
Alle anderen Bereiche wurden **nicht oder nur oberflächlich** (Ordnerstruktur, Dateinamen, keine Codeinhalte) erfasst. Diese Entscheidung folgt der Instruktion, Analysetiefe selbst zu priorisieren und dies transparent zu dokumentieren.
|
||||
|
||||
## 3. Abdeckungstabelle
|
||||
|
||||
| Bereich | Pfad (Auszug) | Tiefe | Bemerkung |
|
||||
|---|---|---|---|
|
||||
| Rechte-/Berechtigungsmodell | `Centron.BL/Administration/Rights`, `Centron.Controllers/Authorization` | **Tief** | Zentrale Klasse `AppRightsBL` vollständig gelesen (860 Zeilen); API-Filter vollständig gelesen. |
|
||||
| Belegwesen (Sales/Receipts) | `Centron.BL/Sales/Receipts/ReceiptBL.cs`, `Centron.Entities/.../Receipts` | **Stichprobenartig, gezielt** | `ReceiptBL.cs` hat 11.441 Zeilen; nur ca. 300-400 Zeilen an thematisch gezielten Stellen gelesen (Status, Rechte, Nummernvergabe, Concurrency, ZUGFeRD). Vollständige Fachlogik (Provisionen, Fracht, Kontingente, Reports, RMA-Anbindung) nicht erfasst. |
|
||||
| Belegnummernvergabe | `Centron.BL/Administration/Company/NumberGroupBL.cs` | **Tief** | Datei vollständig gelesen. |
|
||||
| DSGVO/Datensicherheit | `Centron.BL/Administration/DataSecurity`, `.../Documents/Dsgvo` | **Stichprobenartig** | `DataSecurityBL.cs` (1.900 Zeilen): erste 200 Zeilen gelesen; `DsgvoBL.cs`: erste 100 Zeilen gelesen. |
|
||||
| Digitale Signatur | `Centron.BL/Security/PdfSigningBL.cs`, `CentronNexus/DocumentSigning` | **Stichprobenartig, gezielt** | Backend-Teil (90 Zeilen) gelesen; Blazor-UI-Komponenten nur an Dateinamen/Struktur erkannt, nicht im Detail gelesen. |
|
||||
| CentronNexus (Web-Kundenportal) | `src/nexus/CentronNexus` | **Sehr oberflächlich** | Nur Ordnerstruktur und eine Datei (`WebReceiptOverview.razor`, 90 von vermutlich mehr Zeilen) gelesen. WebCart, ServiceBoard, ProductionOrderManagement, Management, Settings nicht inhaltlich erfasst. |
|
||||
| Ticketing/Helpdesk | `Centron.Entities/.../CustomerArea/Support` | **Datenmodell tief, Fachlogik nicht** | Entitäten `Helpdesk.cs`, `HelpdeskStateBase.cs` vollständig gelesen; zugehörige BL-Klasse(n) nicht identifiziert/gelesen. |
|
||||
| Zeit-/Timer-Fakturierung | `Centron.WPF.UI/.../TimerBilling`, `Centron.BL/Time` | **Sehr punktuell** | Nur der Diff eines einzelnen Commits (baa9e7bd9b) gelesen; restliches Modul nicht erfasst. |
|
||||
| Lager/Artikel | `Centron.BL/Warehousing/ArticleBL.cs` | **Punktuell** | Eine Methode (~50 Zeilen) von vermutlich mehreren tausend Zeilen der Datei gelesen; restliche 15 Klassen des Ordners nicht erfasst. |
|
||||
| API-Authentifizierung | `Centron.Host/CentronHost.cs`, `Centron.Controllers/Authorization` | **Gezielt tief** | Relevante Konfigurationsblöcke vollständig gelesen; restlicher Host-Code (Startup, Middleware, DI) nicht. |
|
||||
| Lizenzmodell | `Centron.Interfaces/.../LicenseGuids.cs` | **Tief** | Datei vollständig gelesen. `LicenseManager.cs` selbst nicht geöffnet. |
|
||||
| Deployment/Docker | `docker/c-entron-webservice/Dockerfile` | **Ein Artefakt tief** | Ein Dockerfile vollständig gelesen; weitere 5 Dockerfiles, Docker-Compose-Dateien, WixSharp-Installer, Azure-Pipelines nicht gelesen. |
|
||||
| Administration (Kernmodul, 959 Dateien) | `Centron.BL/Administration/*` | **Nur Teilbereiche** | Nur Rights, DataSecurity, Company/NumberGroup, Documents/Dsgvo gelesen; übrige ~950 Dateien (u. a. Mandanten-/Employee-/Lizenzverwaltung im Detail, FileManagement, Logins-Kernlogik) nicht erfasst. |
|
||||
| WebServices (464 Dateien) | `Centron.BL/WebServices/*` | **Nicht analysiert** | Nur Dateinamen/Grep-Treffer zur Rechteprüfung gesichtet, keine Datei vollständig gelesen. |
|
||||
| Accounting/Finances/Buying/Purchasing | `Centron.BL/{Accounting,Finances,Buying,Purchasing}` | **Sehr punktuell** | `IncomingPaymentBL.cs` vollständig (klein), restliche ~20 Dateien nicht gelesen. |
|
||||
| CustomerArea/BusinessPartner (Kundenstamm) | `Centron.BL/CustomerArea`, `Centron.Entities/.../Businesspartner` | **Nicht analysiert** | Nur Ordnerstruktur/Dateinamen gesichtet; keine Kundenstamm-BL-Klasse gelesen. |
|
||||
| WPF-Desktopclient (UI-Schicht) | `Centron.WPF.UI/Modules/*` (30 Module) | **Nicht analysiert** | Nur Modulnamen erfasst; UI-Code/ViewModels nicht gelesen (Ausnahme: der eine TimerBilling-Commit-Diff). |
|
||||
| Restliche ~65 BL-Module | `Centron.BL/{AppointmentRequests, ArtificialIntelligence, Calendar, ChangeTracking, Chats, ..., WebVersion}` | **Nicht analysiert** | Ausschließlich Ordnernamen aus Verzeichnislisting bekannt; keine Dateiinhalte gesichtet. |
|
||||
| DAO-Schicht (ORM-Mappings) | `Centron.DAO/*` | **Nicht analysiert** | Nur implizit über Aufrufe in gelesenen BL-Klassen (NHibernate-Nutzungsmuster) erschlossen. |
|
||||
| Datenbankschemata/Migrationsskripte | (keine `.sql`-Dateien im Repository gefunden) | **Nicht vorhanden/nicht auffindbar** | Suche nach `*.sql` ergab 0 Treffer; Schema-Erkenntnisse stammen ausschließlich aus Raw-SQL-Strings innerhalb der C#-Fachlogik. |
|
||||
| Tests (`tests/*`) | `tests/Centron.Tests.*`, `tests/PlaywrightTests` | **Nicht analysiert** | Nur Vorhandensein und grobe Struktur (Playwright-E2E-Tests, Integrationstests) zur Kenntnis genommen; keine Testfälle gelesen. Hätten zusätzliche Belege/Bestätigungen für Hypothesen liefern können. |
|
||||
| Externe API-Integrationen (`src/apis/*`) | Centron.APIs.*, Centron.Api.Gls, Centron.Api.Shipcloud, Centron.Api.EbInterface | **Nicht analysiert** | Nur Ordnernamen bekannt (deuten auf EDI-/Versand-/Bonitäts-/Preisvergleichs-Integrationen hin). |
|
||||
| Dokumentation (`docs/*`) | `docs/features`, `docs/guides`, `docs/operations`, `docs/reference` | **Nicht systematisch ausgewertet** | Nur Ordnerstruktur gesehen; hätte vermutlich zusätzliche SEKUNDÄR-Belege und Klärung von Hypothesen liefern können (bewusst nicht vertieft, um den Fokus auf Primärcode zu halten). |
|
||||
| Change-Historie (Commits/Tickets) | `git log` | **Punktuell** | 5 jüngste Commits als Ausgangspunkt gesichtet (2 davon als KONTEXT-Beleg verwendet: C-Sign-Commit, TimerBilling-Rechte-Commit); keine systematische Auswertung der gesamten Historie. |
|
||||
|
||||
## 4. Konsistenzcheck über das Anforderungs-Set
|
||||
|
||||
Durchgeführt gegen StRS.md (20 Anforderungen), SyRS.md (34 Anforderungen), SwRS.md (28 Anforderungen) und Traceability.md:
|
||||
|
||||
- **Doppelte/mehrfach vergebene IDs:** Keine gefunden. StRS-001 bis StRS-020, SyRS-001 bis SyRS-034, SwRS-001 bis SwRS-028 sind jeweils lückenlos, aufsteigend und eindeutig vergeben.
|
||||
- **Anforderungen ohne Beleg:** Keine gefunden. Jede der 82 Anforderungen (20+34+28) führt mindestens einen klassifizierten Beleg (PRIMÄR/SEKUNDÄR/KONTEXT).
|
||||
- **Risikobereiche ohne PRIMÄR-Beleg:** Alle Anforderungen zu Sicherheit (Rechte, Authentifizierung), Abrechnung/Fakturierung (Nummernvergabe, Zahlungsstatus, ZUGFeRD) und Berechtigungen führen mindestens einen PRIMÄR-Beleg. Ausnahme mit expliziter Kennzeichnung: **SyRS-026** (Kombinationsverhalten mehrerer Autorisierungsattribute) stützt sich nur auf einen SEKUNDÄR-Beleg (README) und wurde daher vollständig als `[HYPOTHESE]` und `Status: [HYPOTHESE]` markiert statt als "belegt" geführt.
|
||||
- **Tracelinks auf nicht existierende IDs:** Keine gefunden. Alle in SyRS.md referenzierten StRS-IDs und alle in SwRS.md referenzierten SyRS-IDs existieren in den jeweiligen Zieldateien (manuell gegen Traceability.md abgeglichen).
|
||||
- **Verwaiste SyRS ohne SwRS-Entsprechung:** SyRS-030 (Containerisierung), SyRS-032 (DB-Technologie), SyRS-034 (Legacy-Schema), SyRS-028 (Zeitzone), SyRS-031 (DevExpress-Abhängigkeit) haben keine dedizierte, methodengenaue SwRS-Anforderung, da es sich um Deployment-/Architektur-Querschnittsthemen ohne einzelne Codemethode als Beleg handelt. Dies ist in Traceability.md explizit vermerkt und als bewusste Scoping-Grenze zu werten, nicht als Fehler.
|
||||
- **Konsolidierungskandidaten:** Zwei Fälle wurden im Feld `Konsolidierung` markiert (SyRS-009/SyRS-013 zur Methode `UpdateReceiptIsPaid`; siehe auch Doppelnennung von SwRS-010 und SwRS-017 in der Traceability-Tabelle). Weitere Redundanzen innerhalb der nicht analysierten ~85 % der Codebasis konnten in dieser Iteration nicht geprüft werden (siehe Abschnitt 6).
|
||||
|
||||
## 5. Belegklassifikation – statistische Übersicht
|
||||
|
||||
Näherungsweise Auszählung über alle 82 Anforderungen (StRS+SyRS+SwRS):
|
||||
|
||||
- Anforderungen mit mindestens einem **PRIMÄR**-Beleg: 80 von 82 (~98 %)
|
||||
- Anforderungen **ausschließlich** mit SEKUNDÄR/KONTEXT-Beleg: SyRS-026 (1 Anforderung, explizit als Hypothese geführt); Belege vom Typ KONTEXT wurden generell nur ergänzend, nie als Alleinbeleg für "belegt"-Status verwendet (Ausnahme s. o.)
|
||||
- Anforderungen mit Status `[HYPOTHESE]`: 1 (SyRS-026); zusätzlich 10 tiefergehende Einzelhypothesen in Hypothesen.md, die sich jeweils auf Detailaspekte belegter (nicht als Hypothese geführter) Anforderungen beziehen
|
||||
- Anforderungen mit Status `belegt; Workaround`: 2 (StRS-014, SwRS-018 – identifizierter Stub in der DSGVO-Bereinigungsausführung)
|
||||
|
||||
Die Belegdichte ist in den priorisierten Tiefenbereichen hoch (siehe Abschnitt 2); sie sagt nichts über die Belegdichte in den **nicht analysierten** ~85 % der Codebasis aus.
|
||||
|
||||
## 6. Selbstbewertung
|
||||
|
||||
**Vollständig analysiert** (im Sinne von: zentrale Datei(en) des Themas vollständig gelesen): Rechte-/Rollenmodell (`AppRightsBL.cs`), Belegnummernvergabe (`NumberGroupBL.cs`), Lizenzkatalog (`LicenseGuids.cs`), API-Authentifizierungskonfiguration (relevanter Ausschnitt aus `CentronHost.cs`), Authorization-Attribute der API, PDF-Signatur-Konfiguration (`PdfSigningBL.cs`, Kernausschnitt), Belegstatus-Enum, Helpdesk-Kern-Entität.
|
||||
|
||||
**Nur stichprobenhaft analysiert:** Belegwesen/Sales (`ReceiptBL.cs` – größte Einzeldatei der Codebasis mit über 11.000 Zeilen, davon < 5 % gelesen), DSGVO/Datensicherheit (`DataSecurityBL.cs` – ca. 10 % gelesen), Lagerbestand/Artikelpreise (`ArticleBL.cs` – ein einzelner Methodenausschnitt), CentronNexus-Webanwendung (eine von hunderten .razor-Dateien), Administration-Modul (4 von geschätzt weit über 100 fachlich relevanten Klassen).
|
||||
|
||||
**Gar nicht analysiert:** WebServices-Schicht (464 Dateien), gesamter WPF-Desktopclient jenseits eines einzelnen Commit-Diffs (30 Module), DAO-/Mapping-Schicht, alle externen API-Integrationsprojekte (EDI, Versand, Bonität), Test-Suiten, Dokumentation (`docs/`), ca. 65 weitere BL-Modulordner, Datenbankschemata/-migrationen (keine `.sql`-Dateien im Repository auffindbar – Schema muss aus Raw-SQL-Strings in der Fachlogik oder aus einer echten DB-Instanz erschlossen werden), Deployment-Artefakte jenseits eines Dockerfiles (WixSharp-Installer, Azure-Pipelines, Docker-Compose).
|
||||
|
||||
**Wo war der Beleg dünn?** Am dünnsten belegt sind: (a) die Fachlogik-Vollständigkeit innerhalb `ReceiptBL.cs` – die hier dokumentierten Regeln sind real und primär belegt, erheben aber keinen Anspruch auf Vollständigkeit der Belegkette-Zustandsmaschine (siehe Hypothese H-07); (b) die serverseitige Durchsetzung der Helpdesk-Bearbeitungssperre (nur Datenfeld, nicht die durchsetzende Methode gefunden, H-02); (c) das Token-Sicherheitsmodell des Web-Angebots (nur die UI-Route, nicht der validierende Service, H-01); (d) die Attribut-Kombinationslogik der API-Autorisierung (nur Dokumentation, H-03, konsequent als einzige Anforderung mit Status `[HYPOTHESE]` geführt statt "belegt").
|
||||
|
||||
**Welche Erkenntnisse legen einen Nachschlag in einer Folgeiteration nahe?**
|
||||
|
||||
1. **DSGVO-Bereinigung ist ein funktionaler Stub** (`DataSecurityExecuteCleanUp`) – dies ist der gewichtigste Einzelbefund dieser Iteration und sollte vorrangig mit Fachexperten validiert werden (ggf. wurde die Ausführung bewusst in ein anderes, hier nicht gefundenes Modul verlagert, oder es handelt sich tatsächlich um eine offene Lücke).
|
||||
2. **`ReceiptBL.cs` (11.441 Zeilen) als "God Class"** sollte in einer Folgeiteration systematisch in Abschnitte zerlegt und vollständig durchgearbeitet werden – hier ist mit Abstand die höchste Dichte an weiteren, noch unentdeckten Geschäftsregeln zu erwarten.
|
||||
3. **CentronNexus** sollte als eigenständiger Schwerpunkt behandelt werden: Da hier bereits eine Web-/Blazor-Neuimplementierung großer Teile des Kundenportals existiert, ist für die im Auftrag genannte Zielsetzung ("belastbare Basis für eine Web-/SaaS-Neuimplementierung") eine Bestandsaufnahme dieses Moduls voraussichtlich wertvoller als eine Neuentwicklung "auf der grünen Wiese".
|
||||
4. **WebServices-Schicht (464 Dateien)** verbindet vermutlich UI/API mit der BL-Schicht und wurde komplett ausgelassen; sie dürfte weitere SyRS-relevante Schnittstellenregeln enthalten.
|
||||
5. **Administration-Modul (959 Dateien)** ist der größte BL-Ordner und wurde nur zu einem kleinen Bruchteil (Rights, DataSecurity, NumberGroup, Dsgvo) untersucht – Mandanten-, Mitarbeiter- und Lizenzverwaltung im Detail stehen noch aus.
|
||||
6. Eine **Datenbank-Schema-Extraktion** (z. B. per Zugriff auf eine echte/leere Instanz oder über NHibernate-Mapping-Dateien in `Centron.DAO`) würde die aktuell nur aus Raw-SQL-Fragmenten erschlossenen Datenstrukturen (Tabellen wie `Sichtrus`, `Ang`, `Auf`, `Lief`) vollständig und verlässlich dokumentieren.
|
||||
|
||||
## 7. Verwendete Werkzeuge und Einschränkungen
|
||||
|
||||
Es wurde ausschließlich statische Analyse mit Dateisystem-Suchwerkzeugen (Glob, Grep) und direktem Lesen von Quelltextdateien durchgeführt; keine Codeausführung, kein Build, kein Datenbankzugriff. Es standen keine spezialisierten Agenten und keine MCP-Server zur Verfügung (Vorgabe der Versuchsanordnung V1 Baseline). Alle Aussagen in StRS.md, SyRS.md und SwRS.md sind auf die in Abschnitt 3 als "Tief" oder "Stichprobenartig, gezielt" gekennzeichneten Bereiche zurückzuführen; keine Datei aus als "Nicht analysiert" gekennzeichneten Bereichen wurde als Beleg herangezogen.
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
# Glossar
|
||||
|
||||
Domänenbegriffe, wie sie in StRS/SyRS/SwRS verwendet werden. Technische Bezeichner (Klassen, Methoden, Tabellen) bleiben im Original; die Erklärung ordnet sie fachlich ein.
|
||||
|
||||
| Begriff | Erklärung | Technischer Beleg |
|
||||
|---|---|---|
|
||||
| **Beleg** | Sammelbegriff für alle kaufmännischen Dokumente eines Geschäftsvorfalls (Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift sowie deren Lieferanten-Pendants Bestellung, Wareneingang, WE-Kalkulation, Lieferantengutschrift). | `ReceiptBase` (Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs), `CentronObjectKindNumeric` |
|
||||
| **Belegkette** | Die fachlich zusammenhängende Folge von Belegen, die auseinander hervorgehen (z. B. Angebot → Auftrag → Lieferschein → Rechnung). Positionen können "weitergeführt" werden. | `ReceiptBL.GetReceiptForwardedInto` |
|
||||
| **Belegstatus (ReceiptState)** | Fester, dreiwertiger Status jedes Verkaufs-/Einkaufsbelegs: `Active` ("offen"), `Completed` ("abgeschlossen"), `Canceled` ("storniert"). Gilt einheitlich für alle Belegarten. | `ReceiptState` enum |
|
||||
| **I3D** | Durchgängige Namenskonvention für den technischen Primärschlüssel (Integer-ID) nahezu aller Entitäten im System (z. B. `AppUser.I3D`, `Customer.I3D`). Historisch aus dem Delphi-Vorgängersystem übernommen. | durchgängig in Entities, z. B. `AppRight.cs`, Kommentar in `CentronObjectKindNumeric.cs` Zeile 14 |
|
||||
| **Mandant (Mandator)** | Oberste Organisationseinheit im Mehrmandantenmodell; besitzt eigene Nummernkreise, Lizenzen und Stammdaten. | `MandatorBL`, `NumberGroup.MandatorI3D` |
|
||||
| **Filiale (Branch)** | Untergliederung eines Mandanten; viele Rechte und Nummernkreise können auf "nur eigene Filiale" eingeschränkt werden. | `AppGroup.BranchI3D`, `UserRightsConst...MANAGE_RIGHTS_ONLY_OWN_BRANCH`, `BranchBL.IsBranchEqual` |
|
||||
| **AppRight / Sichtrecht** | Einzelnes, hierarchisch organisiertes Zugriffsrecht (z. B. "Rechnungen anzeigen – nur Eigene"), historisch in der DB-Tabelle `Sichtrus` verwaltet. | `AppRight.cs`, SQL-Tabellen `Sichtrus`/`Sichgrup`/`Sichmemb` |
|
||||
| **AppGroup (Rechte-/Benutzergruppe)** | Gruppe, der Rechte zugeordnet werden und der Benutzer angehören (rollenbasierte Zugriffssteuerung, RBAC). | `AppGroup`, `AppGroupRightAssignment` |
|
||||
| **WebAccount** | Login-Konto für externe Kunden im Kundenportal; besitzt ein eigenes, einfacheres Rechtemodell (`WebRights`) getrennt von internen `AppRight`en und darf interne Belege grundsätzlich nicht einsehen. | `WebAccount`, `WebRights.cs`, `ReceiptBL.CanUserViewReceipt` |
|
||||
| **Web-Token-Link (WebOffer)** | Öffentlich erreichbarer, tokenbasierter Link (`/weboffer/{Token}`), über den ein Kunde ein Angebot ohne Benutzeranmeldung einsehen und annehmen kann. | `WebReceiptOverview.razor` |
|
||||
| **NumberGroup / Nummernkreis** | Zähler-Objekt pro Mandant/Filiale und Belegart, aus dem fortlaufende, kollisionsgeprüfte Belegnummern gezogen werden. | `NumberGroupBL`, `NumberGroupEnum` |
|
||||
| **CentronObjectKindNumeric** | Zentrale Enumeration, die jede Objektart im Gesamtsystem (Belege, Stammdaten, Assets, Module) mit einer festen numerischen ID versieht; Basis für Web-Service-Kompatibilität. | `CentronObjectKindNumeric.cs` |
|
||||
| **Recht "nur Eigene"/"nur eigene Filiale"** | Wiederkehrendes Berechtigungsmuster: ein Benutzer darf Objekte eines Typs nur sehen/bearbeiten, wenn er sie selbst erstellt hat bzw. sie zu seiner Filiale gehören. | `AppRightsBL.GetAssignableAdminRightI3Ds` (Rechtekommentare), `ReceiptBL.CanUserEditReceipt` |
|
||||
| **Konkurrenzsteuerung (ConcurrencyControlGuid)** | Optimistisches Sperrverfahren: jede Beleg-Version trägt eine GUID; weicht die beim Schreiben übergebene GUID vom aktuellen Stand ab, wird die Änderung abgelehnt ("wurde in der Zwischenzeit geändert"). | `ReceiptBase.ConcurrencyControlGuid`, `ReceiptBL.UpdateReceiptIsPaid` |
|
||||
| **Belegversion (Version)** | Verkaufsbelege sind versioniert; eine neue Version muss lückenlos auf die vorherige folgen (Versionsnummer exakt +1) oder die erste Version sein. | `ReceiptBL.SaveReceipt` (Validierung `isFirstVersion`/`isCurrentVersion`/`isNextVersion`) |
|
||||
| **ZUGFeRD** | Deutscher/europäischer Standard für hybride E-Rechnungen (PDF mit eingebettetem strukturiertem XML); wird für Rechnungen/Gutschriften automatisch erzeugt, wenn aktiviert. | `ReceiptBL` (Zeile ~3266 ff.), `InvoiceZugferdBL` |
|
||||
| **C-Sign / DocumentSigning** | Sammelbegriff für die digitale/elektronische Unterschrift von Dokumenten: serverseitige PDF-Zertifikatssignatur (`PdfSigningBL`) sowie browserbasierte Unterschrift per Signaturpad im Kundenportal. | `PdfSigningBL.cs`, `DocumentSigningPage.razor`, `IsolatedSignaturePad.razor` |
|
||||
| **DSGVO-Modul** | Funktionsbereich zur Umsetzung datenschutzrechtlicher Anforderungen: Auftragsverarbeitungsvertrags-Vorlagen, Lösch-/Bereinigungsstatistiken und (laut Code) noch nicht vollständig implementierte automatische Datenbereinigung. | `DsgvoBL.cs`, `DataSecurityBL.cs` |
|
||||
| **Helpdesk / Ticket** | Vorgang im Kundenservice-/Ticketsystem; Status ist – anders als bei Belegen – keine feste Enumeration, sondern konfigurierbare Stammdaten (`HelpdeskStateBase`). | `Helpdesk.cs`, `HelpdeskStateBase.cs` |
|
||||
| **Timer-Fakturierung (TimerBilling)** | Modul, das erfasste Zeiten (z. B. aus Tickets) gebündelt in Rechnungen oder Lieferscheine überführt; das Fakturierungsdatum ist nur änderbar, wenn eine entsprechende Berechtigung/Einstellung vorliegt. | `TimerBillingSettingsPageViewModel.cs` |
|
||||
| **Lizenz-/Modulmodell** | Produktfunktionen sind in einzeln lizenzierbare Module gegliedert (klassische Einzellizenzen und neueres Subscription-Modell); Verfügbarkeit wird zur Laufzeit über `LicenseManager` geprüft. | `LicenseGuids.cs`, `LicenseManager.cs`, `CentronHostedAuthorization.cs` |
|
||||
| **CentronNexus** | Separate ASP.NET-Blazor-Webanwendung (Kundenportal/Self-Service), die u. a. Web-Angebote, Web-Warenkorb, Service-Board und digitale Unterschrift bereitstellt; kommuniziert mit dem Hauptbackend über einen eigenen "SecretKey"-Kanal. | `src/nexus/CentronNexus/*`, `SecretKeyRequirement` |
|
||||
| **Raw-EK (RawEk1/RawEk2)** | Historisierter Einkaufspreis eines Artikels: der zuletzt gebuchte Wareneingangspreis (RawEk1) und der vorherige (RawEk2) werden mit Datum und Quellbeleg gespeichert. | `ArticleBL.UpdateArticlePurchasePriceThroughStockBooking` |
|
||||
| **BaseBL / DAOSession** | Architekturmuster: jede Geschäftslogik-Klasse (`*BL`) erhält eine `DAOSession` (NHibernate-Session-Wrapper) injiziert und kapselt Datenzugriff + Fachregeln. | durchgängig in `Centron.BL`, z. B. `AppRightsBL : BaseBL` |
|
||||
| **Result / Result\<T\>** | Einheitlicher Rückgabetyp für Fachoperationen mit Status (`Success`/`Error`), Nachricht und optionalem `MessageCode` (z. B. `RightCheckFailed`, `ChangedByOtherInstance`) statt Exceptions für erwartbare Fachfehler. | `Result`, `DefaultMessageCodes` |
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
# Hypothesen
|
||||
|
||||
Sammlung aller mit `[HYPOTHESE]` markierten Aussagen aus StRS/SyRS/SwRS sowie weiterer, während der Analyse aufgefallener unbestätigter Annahmen, jeweils mit der offenen Frage, die zur Bestätigung/Widerlegung fehlt.
|
||||
|
||||
| # | Bezug | Hypothese | Fehlende Information zur Bestätigung |
|
||||
|---|---|---|---|
|
||||
| H-01 | StRS-013, SyRS-016, SwRS-017 | Der Mechanismus zur Gültigkeitsprüfung, zum Ablauf und zum Widerruf von Web-Angebots-Token (`/weboffer/{Token}`) folgt einer definierten Sicherheitslogik (z. B. zeitlich begrenzt, einmalig verwendbar, an den Beleg gebunden). | Der serverseitige Endpunkt/Service, der den Token gegen einen Beleg auflöst (vermutlich in `ICentronService` oder einem Controller unter `src/nexus/CentronNexus/Controllers`), wurde nicht gelesen. Zu prüfen: Token-Generierung, -Speicherung, -Ablaufdatum, -Invalidierung nach Annahme. |
|
||||
| H-02 | SyRS-020, SwRS-020 | Die Sperrfelder `LockUserName`/`LockUser` der Helpdesk-Entität werden serverseitig (nicht nur clientseitig/UI) durchgesetzt, sodass ein zweiter Bearbeiter tatsächlich am Speichern gehindert wird. | Die BL-Methode, die beim Speichern eines Helpdesk-Datensatzes die Sperre prüft (vermutlich in einer HelpdeskBL-Klasse), wurde im Rahmen dieser Iteration nicht identifiziert/gelesen. |
|
||||
| H-03 | SyRS-026 | Mehrere Autorisierungsattribute auf Controller- und Action-Ebene ([AuthorizeUserRight] etc.) werden kumulativ (UND-verknüpft) ausgewertet, wie im README dokumentiert. | Nur die README (SEKUNDÄR) wurde als Beleg herangezogen; das tatsächliche Laufzeitverhalten der ASP.NET-Core-Filterpipeline bei mehreren TypeFilterAttribute-Instanzen wurde nicht im Projekt-Code oder per Test verifiziert. |
|
||||
| H-04 | SyRS-028 | Die im Docker-Image fest gesetzte Zeitzone `Europe/Berlin` wirkt sich unmittelbar auf fachliche Zeitstempel (z. B. `CreatedAt`, `Date` von Belegen) aus und nicht nur auf Infrastruktur-/Log-Zeitstempel. | Die Entitäts-/DB-Spalten wurden nicht daraufhin geprüft, ob Zeitstempel mit `DateTime.Now` (serverzeitzone-abhängig) oder `DateTimeOffset`/UTC gespeichert werden. |
|
||||
| H-05 | StRS-008, SyRS-010 (Notiz, nicht als eigene SyRS geführt) | Die Belegnummernvergabe (`NumberGroupBL`) ist zwar kollisionsfrei, aber nicht nachweislich lückenlos (GoBD-Anforderung an fortlaufende Rechnungsnummern) – bei fehlgeschlagenen Transaktionen nach Zählerinkrement könnten Lücken entstehen. | Es wurde nicht geprüft, ob und wie das System nachträglich prüft/dokumentiert, dass eine reservierte Nummer tatsächlich einem gespeicherten Beleg zugeordnet wurde (Transaktionsgrenzen von `GetNextNumber` vs. `SaveReceipt` nicht im Detail nachvollzogen). |
|
||||
| H-06 | Sicherheitsmodell allgemein (StRS-001, notes-security.md) | Der Rechtekatalog (welches `AppRight.I3D` fachlich welche Aktion freischaltet) ist vollständig datenbankgetrieben (Stammdaten) und nicht zusätzlich über eine zentrale Enum/Konstanten-Datei im Code dokumentiert – mit Ausnahme punktueller `UserRightsConst`-Konstanten für einzelne, im Code referenzierte Rechte. | Es wurde keine vollständige Quelle gefunden, die alle vergebenen Recht-IDs mit ihrer fachlichen Bedeutung auflistet (nur Einzelbelege über Inline-Kommentare, z. B. in `GetAssignableAdminRightI3Ds`). Eine SQL-Abfrage auf die Tabelle `Sichtrus`/`AppRight` in einer echten Datenbankinstanz wäre nötig. |
|
||||
| H-07 | StRS-006, ReceiptBL allgemein | Es existiert eine vollständige, für jede Belegart identische Zustandsübergangs-Matrix (welche Aktionen sind in welchem ReceiptState erlaubt), über die hier belegten Einzelregeln hinaus. | `ReceiptBL.cs` umfasst 11.441 Zeilen; nur ca. 300 Zeilen wurden im Detail gelesen (stichprobenartig). Eine vollständige Zustandsübergangs-Matrix wurde nicht erhoben. |
|
||||
| H-08 | StRS-015, Helpdesk-Modul | Tickets besitzen ein Eskalationsverfahren, das automatisiert auf Basis von `EscalationLevel`/`DueDate` ausgelöst wird (z. B. durch einen Hintergrunddienst). | Es wurde kein Scheduler/Hintergrunddienst-Code gelesen, der `EscalationLevel` auswertet; nur das Datenfeld selbst wurde bestätigt (`EscalationServer`-Lizenz in `LicenseGuids.cs` deutet auf einen solchen Dienst hin, wurde aber nicht untersucht). |
|
||||
| H-09 | StRS-011, ZUGFeRD | `InvoiceZugferdBL` erzeugt tatsächlich schemakonforme ZUGFeRD-/Factur-X-XML-Daten (korrekte Profile, Pflichtfelder). | Die Klasse `InvoiceZugferdBL` selbst wurde nicht geöffnet/gelesen; nur ihr Aufruf und die Aktivierungsbedingung wurden verifiziert. |
|
||||
| H-10 | StRS-018, CentronNexus-Lizenzierung | Die Lizenz `CentronNexus` (in `LicenseGuids.cs` gelistet) steuert eigenständig die Verfügbarkeit der CentronNexus-Webanwendung als Ganzes (analog zu `CentronHosted` für einzelne API-Bereiche). | Der Prüfpfad, der diese spezifische Lizenz zur Laufzeit auswertet, wurde nicht identifiziert (nur `CentronInternal` wurde im Detail verifiziert). |
|
||||
|
||||
## Hinweis
|
||||
|
||||
Diese Liste erhebt keinen Anspruch auf Vollständigkeit gegenüber der Gesamtcodebasis (15.554 C#- und 1.233 XAML-Dateien) – sie dokumentiert ausschließlich Unsicherheiten, die innerhalb der in dieser Iteration tatsächlich analysierten Bereiche aufgefallen sind. Weitere, hier nicht analysierte Module enthalten mit hoher Wahrscheinlichkeit zusätzliche offene Fragen (siehe Analysebericht.md, Abschnitt "Nicht analysierte Bereiche").
|
||||
+407
@@ -0,0 +1,407 @@
|
||||
# Stakeholder Requirements Specification (StRS)
|
||||
|
||||
Reverse-engineert aus der Codebasis "CentronERP" (c-entron ERP-Suite). Ebene: fachliche Sicht, Akteure, Geschäftsziele, gemäß ISO/IEC/IEEE 29148:2018.
|
||||
|
||||
Zur Belegklassifikation, Statuswerten und Formatfeldern siehe Vorgaben im Auftrag. Alle Aussagen sind entweder `belegt`, `belegt; Workaround` oder `[HYPOTHESE]`.
|
||||
|
||||
## Akteursübersicht (aus dem Code abgeleitet)
|
||||
|
||||
| Akteur | Beschreibung | Kernbeleg |
|
||||
|---|---|---|
|
||||
| Interner Benutzer (AppUser) | Mitarbeiter mit Login im Hauptsystem (WPF-Client/API), Mitglied einer oder mehrerer Rechtegruppen (`AppGroup`) | `AppUser`, `AppRightsBL` |
|
||||
| Systemadministrator | Interner Benutzer mit Rechteverwaltungs-/Systemrechten (`UserRightsConst.Administration.*`) | `AppRightsBL.SaveRightGroup` |
|
||||
| Web-Portal-Kunde (WebAccount) | Externer Kunde mit eigenem, eingeschränktem Login im Kundenportal | `WebAccount`, `WebRights` |
|
||||
| Anonymer Angebotsempfänger | Externe Person ohne Login, die über einen Token-Link ein Angebot einsieht/annimmt | `WebReceiptOverview.razor` |
|
||||
| Vertrieb/Innendienst | Interner Benutzer, der Angebote/Aufträge erstellt und pflegt | `ReceiptBL` (Belegarten Offer/Order) |
|
||||
| Buchhaltung/Controlling | Interner Benutzer mit Sonderrechten für Zahlungsvorgänge, Rechnungswesen | `UserRightsConst.Controlling.Finances.INCOMING_PAYMENT_TRANSACTIONS` |
|
||||
| Datenschutzbeauftragter | Interner Benutzer mit DSGVO-Modulrecht | `UserRightsConst.DsgvoModule` |
|
||||
| Lager-/Einkaufsmitarbeiter | Interner Benutzer, der Artikelstamm und Einkaufspreise pflegt | `ArticleBL` |
|
||||
| Helpdesk-/Servicemitarbeiter | Interner Benutzer, der Tickets bearbeitet und Zeiten erfasst | `Helpdesk`, `HelpdeskTimer` |
|
||||
| c-entron (Hersteller/Lizenzgeber) | Definiert Produktmodule und deren Lizenzierung | `LicenseGuids`, `LicenseManager` |
|
||||
| Externes System | EDI-Partner, Zahlungsdienstleister (z. B. FinAPI), Versanddienstleister (z. B. GLS, Shipcloud), CentronNexus als eigenständige Webanwendung | `Centron.APIs.*`, `Centron.Api.Gls`, `Centron.Api.Shipcloud`, `SecretKeyRequirement` |
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: StRS-001
|
||||
Titel: Rollenbasierte Zugriffssteuerung für interne Benutzer
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Interner Benutzer, Systemadministrator
|
||||
Vorbedingung: Ein interner Benutzer ist am System angemeldet.
|
||||
Fakt: Rechte (AppRight) werden Gruppen (AppGroup) zugeordnet; Benutzer erhalten ihre Rechte ausschließlich über die Mitgliedschaft in einer oder mehreren Gruppen (AppRightsBL.GetRightsFromCurrentUser, Zeile 63-87; HasUserRight, Zeile 644-649).
|
||||
Aussage: Das System soll den Zugriff auf Funktionen und Daten ausschließlich auf Basis von Rechten steuern, die einem Benutzer über seine Gruppenzugehörigkeit zugewiesen sind (rollenbasierte Zugriffskontrolle, RBAC).
|
||||
Ergebnis: Ein Benutzer kann nur Funktionen ausführen bzw. Daten sehen, für die mindestens eine seiner Gruppen das entsprechende Recht besitzt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Methode HasUserRight (Z. 644-649) - Begründung: Zentrale, tatsächlich aufgerufene Rechteprüfung, JOIN über Gruppenmitgliedschaft (Sichtrus/Sichmemb).
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs (Z. 38-56) - Begründung: ASP.NET-Core-Authorization-Filter, der dieselbe HasUserRight()-Logik auf API-Ebene erzwingt (401/403).
|
||||
- [SEKUNDÄR] src/webservice/Centron.Controllers/Authorization/README.md - Begründung: Dokumentiert das Muster und seine Anwendung an Beispielcontrollern (bestätigend, nicht durchsetzend).
|
||||
Prüfidee: Benutzer ohne die entsprechende Gruppenmitgliedschaft ruft eine rechtegeschützte Aktion auf (API und WPF) → Zugriff wird verweigert (403 bzw. Result.AsError mit RightCheckFailed).
|
||||
Tracelinks: SyRS-001, SyRS-002, SyRS-026
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-002
|
||||
Titel: Eingeschränkter Belegzugriff für Web-Portal-Kunden
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Web-Portal-Kunde (WebAccount)
|
||||
Vorbedingung: Ein externer Kunde ist über ein WebAccount-Login angemeldet.
|
||||
Fakt: CanUserViewReceipt verweigert WebAccount-Logins grundsätzlich die Einsicht interner Belege ("Web-Benutzer haben keine Berechtigung Belege einzusehen."); WebAccounts nutzen ein eigenes, von AppRight getrenntes Rechtemodell (WebRights/WebAccountsRights).
|
||||
Aussage: Das System soll Web-Portal-Kunden grundsätzlich vom direkten Zugriff auf interne Beleglisten/-verwaltung ausschließen und ihnen stattdessen nur explizit über das Kundenportal freigegebene, funktional eingeschränkte Sichten anbieten.
|
||||
Ergebnis: Ein WebAccount-Login erhält bei Versuch, interne Belege einzusehen, eine Fehlermeldung; separate Web-Rechte (WebRights) steuern die im Kundenportal sichtbaren Inhalte.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, CanUserViewReceipt (Z. 10297-10311) - Begründung: Erzwingt die Sperre für IsWebAccountLogin vor jeder fachlichen Prüfung.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, HasWebAccountRight (Z. 666-691) - Begründung: Eigenständiger Rechtemechanismus für WebAccounts (Tabelle WebAccountsRights) getrennt vom internen AppRight-System.
|
||||
Prüfidee: Anmeldung als WebAccount und Aufruf einer internen Beleg-Ansichtsfunktion → Result.AsError mit RightCheckFailed und Text "Web-Benutzer haben keine Berechtigung Belege einzusehen."
|
||||
Tracelinks: SyRS-003, StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-003
|
||||
Titel: Filialbezogene Zugriffsbeschränkung ("nur eigene Filiale")
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Interner Benutzer
|
||||
Vorbedingung: Ein Mandant ist in mehrere Filialen (Branches) untergliedert.
|
||||
Fakt: Zahlreiche Rechte existieren in zwei Varianten – uneingeschränkt und "nur eigene Filiale" – und werden bei Belegbearbeitung (CanUserEditReceipt, Z. 10284-10292) sowie bei der Rechteverwaltung selbst (SaveRightGroup, Z. 391-393; DeleteRightGroup, Z. 355-357) per BranchBL.IsBranchEqual geprüft.
|
||||
Aussage: Das System soll es ermöglichen, den Zugriff auf Belege, Rechtegruppen und weitere Objekte pro Recht wahlweise mandantenweit oder auf die eigene Filiale des Benutzers zu beschränken.
|
||||
Ergebnis: Ein Benutzer mit "nur eigene Filiale"-Recht kann keine Objekte anderer Filialen einsehen/bearbeiten; die Prüfung erfolgt serverseitig, nicht nur in der UI.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, CanUserEditReceipt (Z. 10272-10295) - Begründung: Belegartspezifische Prüfung inkl. Filialvergleich, wirft konkrete Fehlermeldung.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 42-45, 355-357, 391-393, 444-446) - Begründung: Gleiches Muster durchgängig auch in der Rechte-/Gruppenverwaltung selbst angewendet.
|
||||
Prüfidee: Benutzer der Filiale A mit "nur eigene Filiale"-Recht versucht, einen Beleg der Filiale B zu bearbeiten → Fehlermeldung "...einer anderen Filiale zu bearbeiten."
|
||||
Tracelinks: SyRS-004, StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-004
|
||||
Titel: Schutz der Administratoren-Rolle vor versehentlicher Änderung
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Systemadministrator
|
||||
Vorbedingung: Die Rechtegruppe "Administratoren" existiert im System (technisch fest über I3D=6 bzw. Namen identifiziert).
|
||||
Fakt: DeleteRightGroup verweigert das Löschen der Administratoren-Gruppe hart codiert (Z. 359-360); nur eine feste Whitelist von 38 Rechten darf ihr hinzugefügt/entzogen werden (GetAssignableAdminRightI3Ds, Z. 714-759).
|
||||
Aussage: Das System soll verhindern, dass die zentrale Administratoren-Rolle gelöscht wird oder durch Entzug sicherheitskritischer Rechte handlungsunfähig gemacht werden kann.
|
||||
Ergebnis: Löschversuche der Administratoren-Gruppe werden abgelehnt; Rechteänderungen an dieser Gruppe sind auf eine definierte, unkritische Teilmenge begrenzt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, DeleteRightGroup (Z. 348-374) und GetAssignableAdminRightI3Ds (Z. 714-759) - Begründung: Hartkodierte Schutzregel bzw. Whitelist, direkt im Code durchgesetzt.
|
||||
Prüfidee: Löschversuch der Gruppe "Administratoren" → Result.AsError; Versuch, ein nicht in der Whitelist enthaltenes Recht der Admin-Gruppe zu entziehen → Operation liefert false/keine Änderung.
|
||||
Tracelinks: SyRS-005, StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-005
|
||||
Titel: Nachvollziehbarkeit von Rechte- und Gruppenänderungen
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Systemadministrator
|
||||
Vorbedingung: Ein Administrator ändert Rechtezuordnungen, Gruppen oder Gruppenmitgliedschaften.
|
||||
Fakt: Jede Änderung (Recht zu Gruppe hinzufügen/entfernen, Gruppe anlegen/löschen/kopieren, Benutzer zu Gruppe hinzufügen/entfernen) erzeugt einen AppRightLog-Eintrag mit Klartextbeschreibung, ausführendem Benutzer und Zeitstempel (WriteBaseLog, Z. 762-781, sowie die spezialisierten Write*Log-Methoden, Z. 783-857).
|
||||
Aussage: Das System soll alle sicherheitsrelevanten Änderungen an Rechten, Gruppen und Gruppenmitgliedschaften revisionssicher protokollieren.
|
||||
Ergebnis: Zu jeder Rechte-/Gruppenänderung existiert ein nachvollziehbarer Log-Eintrag (Wer, Was, Wann), abrufbar über GetAllAppRightLogs.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Region "Logging" (Z. 761-858) - Begründung: Jede änderende Methode ruft konsequent eine Write*Log-Methode auf.
|
||||
- [SEKUNDÄR] src/backend/Centron.Entities/Entities/Administration/AppRightLog.cs - Begründung: Persistenzstruktur des Protokolls (Kind, Object, Description, CreatedByI3D, CreatedDate).
|
||||
Prüfidee: Nach Zuweisung eines Rechts an eine Gruppe erscheint ein neuer Eintrag in GetAllAppRightLogs mit korrektem Beschreibungstext und Benutzerreferenz.
|
||||
Tracelinks: SyRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-006
|
||||
Titel: Durchgängige Belegkette vom Angebot bis zur Rechnung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb/Innendienst
|
||||
Vorbedingung: Ein Geschäftsvorfall beginnt typischerweise mit einem Angebot oder Auftrag.
|
||||
Fakt: Alle Verkaufsbelege (Angebot, Auftrag, Lieferschein, Abholschein, Rechnung, Gutschrift, Vertrag) leiten von der gemeinsamen Basisklasse ReceiptBase ab und tragen eine einheitliche ReceiptKind-Klassifikation (CentronObjectKindNumeric); ReceiptBL.GetReceiptForwardedInto ermittelt, in welche Folgebelege ein Beleg/eine Position übernommen wurde.
|
||||
Aussage: Das System soll es ermöglichen, einen Geschäftsvorfall durch eine Kette aufeinander aufbauender Belege (Angebot → Auftrag → Lieferschein/Abholschein → Rechnung/Gutschrift) abzubilden und die Herkunft/Weiterführung einzelner Positionen nachvollziehbar zu halten.
|
||||
Ergebnis: Zu jedem Beleg lässt sich ermitteln, aus welchem Vorgängerbeleg er hervorgegangen ist bzw. in welche Folgebelege seine Positionen übernommen wurden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs - Begründung: Gemeinsames Datenmodell aller Belegarten (Number, Version, State, GetReceiptItems/AddItem/RemoveItem als Vertrag).
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (Z. 20-264) - Begründung: Zentrale, im gesamten System verwendete Klassifikation aller Belegarten inkl. Positionsarten (OfferPos, OrderPos, ...).
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, GetReceiptForwardedInto (~Z. 9942) - Begründung: Konkrete Implementierung der Weiterführungs-Logik (nur nicht-stornierte Folgebelege zählen).
|
||||
Prüfidee: Ein Angebot wird in einen Auftrag übernommen; GetReceiptForwardedInto(Angebot) liefert den erzeugten Auftrag als Ziel.
|
||||
Tracelinks: SyRS-007, SyRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-007
|
||||
Titel: Einheitliche Statusführung für alle Belegarten
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb/Innendienst, System
|
||||
Vorbedingung: Ein Beleg wurde angelegt.
|
||||
Fakt: Enum ReceiptState definiert exakt drei Zustände (Active/offen, Completed/abgeschlossen, Canceled/storniert), die für alle Belegarten identisch gelten; automatischer Übergang nach Completed erfolgt z. B. abhängig von Zahlungsbedingungen (ShouldCloseNewReceiptAutomatically).
|
||||
Aussage: Das System soll jeden Beleg unabhängig von seiner Art in genau einem von drei einheitlichen Status (offen, abgeschlossen, storniert) führen und diesen Status als Grundlage für Folgeprozesse (z. B. Zahlungserfassung, E-Rechnungs-Erzeugung) verwenden.
|
||||
Ergebnis: Der Belegstatus ist zu jedem Zeitpunkt eindeutig bestimmt und steuert nachgelagerte Funktionen (z. B. Sperrung stornierter Belege für Zahlungsänderungen).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Enum-Definition mit exakt drei Werten und deutschen Beschreibungen.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 4936-4937, Z. 8347-8355) - Begründung: Tatsächliche Verwendung des Status zur Ablaufsteuerung (Sperre bei Canceled, Auto-Abschluss).
|
||||
Prüfidee: Ein stornierter Beleg kann nicht mehr als bezahlt markiert werden (Fehlermeldung); ein neu angelegter Beleg mit passender Zahlungsbedingung wird automatisch auf "abgeschlossen" gesetzt.
|
||||
Tracelinks: SyRS-009, StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-008
|
||||
Titel: Eindeutige, kollisionsfreie Belegnummernvergabe
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb/Innendienst, Buchhaltung/Controlling
|
||||
Vorbedingung: Ein neuer Beleg (oder Stammdatensatz wie Kunde/Lieferant) wird angelegt und benötigt eine fortlaufende Nummer.
|
||||
Fakt: NumberGroupBL.GetNextNumber/FindNextNumber ermittelt je Nummernkreis (pro Mandant/Filiale und Belegart) die nächste freie Nummer, prüft deren Kollisionsfreiheit gegen die Zieltabelle per SQL-COUNT und schreibt sie unter Bedingungsprüfung (WHERE Current=alterWert) zurück, mit Wiederholungsschleife bei Parallelzugriff.
|
||||
Aussage: Das System soll jedem Beleg und ausgewählten Stammdatenobjekten (Kunde, Lieferant) eine innerhalb ihres Nummernkreises eindeutige, kollisionsfreie Nummer zuweisen, auch bei gleichzeitigem Zugriff mehrerer Benutzer.
|
||||
Ergebnis: Zwei parallel arbeitende Benutzer erhalten niemals dieselbe Belegnummer im selben Nummernkreis.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs, GetNextNumber/FindNextNumber (Z. 50-134) - Begründung: Durchgesetzter Algorithmus inkl. Kollisionsprüfung per Raw-SQL und bedingtem Update.
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, UpdateReceiptNumber (Z. 7265-7285) - Begründung: Aufrufstelle, die die Nummer beim Speichern eines Belegs anfordert; behandelt Sonderfall Belegvorlagen separat.
|
||||
Prüfidee: Zwei simultane Speichervorgänge im selben Nummernkreis führen zu zwei unterschiedlichen, gültigen Nummern (kein Duplikat in der Zieltabelle).
|
||||
Tracelinks: SyRS-010, SyRS-011, StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-009
|
||||
Titel: Datenintegrität bei gleichzeitiger Bearbeitung von Belegen
|
||||
Ebene: StRS
|
||||
Typ: Daten
|
||||
Akteur: Vertrieb/Innendienst, System
|
||||
Vorbedingung: Zwei Benutzer öffnen denselben Beleg gleichzeitig zur Bearbeitung.
|
||||
Fakt: Jeder Beleg trägt ein ConcurrencyControlGuid; Schreiboperationen vergleichen die übergebene GUID mit dem aktuellen Datenbankstand und lehnen die Änderung mit einer definierten Fehlermeldung/MessageCode (ChangedByOtherInstance) ab, wenn sie nicht übereinstimmt. Zusätzlich erzwingt SaveReceipt eine lückenlose Versionsfolge (isFirstVersion/isCurrentVersion/isNextVersion).
|
||||
Aussage: Das System soll verhindern, dass gleichzeitige Änderungen an demselben Beleg zu stillem Datenverlust führen, indem es konkurrierende Schreibversuche erkennt und mit einer eindeutigen Fehlermeldung ablehnt.
|
||||
Ergebnis: Der zweite von zwei konkurrierenden Speicherversuchen wird abgelehnt und der Benutzer über die zwischenzeitliche Änderung informiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 4884-4885, 4939-4940) - Begründung: Konkrete GUID-Vergleichsprüfung mit Fehlerrückgabe vor jeder Datenänderung.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, SaveReceipt (Z. 3562-3578) - Begründung: Zusätzliche Versionsvalidierung als zweite Integritätsebene.
|
||||
Prüfidee: Benutzer A speichert einen Beleg; Benutzer B versucht anschließend, denselben (veralteten) Beleg mit alter ConcurrencyControlGuid zu speichern → Fehler "was changed in the meantime".
|
||||
Tracelinks: SyRS-012, StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-010
|
||||
Titel: Zahlungsstatus-Verwaltung mit rollenspezifischer Ausnahme
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb/Innendienst, Buchhaltung/Controlling
|
||||
Vorbedingung: Ein Rechnungs- oder Gutschriftsbeleg existiert und ist nicht storniert.
|
||||
Fakt: UpdateReceiptIsPaid prüft primär das belegartspezifische Bearbeitungsrecht; fehlt dieses speziell wegen RightCheckFailed, wird alternativ geprüft, ob der Benutzer das Sonderrecht INCOMING_PAYMENT_TRANSACTIONS besitzt (Z. 4920-4934) - Buchhaltung darf demnach den Zahlungsstatus pflegen, auch ohne allgemeines Bearbeitungsrecht am Beleg.
|
||||
Aussage: Das System soll das Setzen des Zahlungsstatus (bezahlt/unbezahlt) eines Belegs entweder Benutzern mit allgemeinem Bearbeitungsrecht am Belegtyp oder Benutzern mit dem spezifischen Recht für Zahlungseingänge gestatten, unabhängig voneinander.
|
||||
Ergebnis: Ein Mitarbeiter der Buchhaltung ohne Verkaufsrechte kann dennoch Zahlungseingänge auf Rechnungen erfassen; storniert Belege sind davon ausgenommen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, UpdateReceiptIsPaid (Z. 4902-4944) - Begründung: Enthält explizit die alternative Rechteprüfung und die Sperre für stornierte Belege.
|
||||
Prüfidee: Benutzer mit ausschließlich INCOMING_PAYMENT_TRANSACTIONS-Recht (ohne allgemeines Bearbeitungsrecht) kann einen Beleg als bezahlt markieren; derselbe Versuch an einem stornierten Beleg schlägt fehl.
|
||||
Tracelinks: SyRS-013, StRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-011
|
||||
Titel: Elektronische Rechnung nach ZUGFeRD-Standard
|
||||
Ebene: StRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Vertrieb/Innendienst, Externes System (Empfänger E-Rechnung)
|
||||
Vorbedingung: ZUGFeRD ist mandanten- oder belegweit aktiviert; der Beleg ist eine Rechnung oder Gutschrift.
|
||||
Fakt: Beim Erzeugen des Belegreports wird für InvoiceClass/CreditVoucherClass geprüft, ob ZUGFeRD aktiv ist (InvoiceZugferdBL.IsZugferdEnabled oder lokale Beleg-Einstellung) und der Beleg nicht storniert ist; ist dies der Fall, wird eine PDF mit eingebettetem strukturiertem Datensatz erzeugt.
|
||||
Aussage: Das System soll für Rechnungen und Gutschriften bei aktivierter Einstellung automatisch eine ZUGFeRD-konforme, hybride E-Rechnung (PDF mit eingebettetem XML) erzeugen.
|
||||
Ergebnis: Der erzeugte Belegreport für Rechnungen/Gutschriften enthält bei aktivierter Einstellung eingebettete strukturierte Rechnungsdaten gemäß ZUGFeRD.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 3266-3274) - Begründung: Bedingte, tatsächlich ausgeführte Weiche zur ZUGFeRD-Erzeugung inkl. Ausschluss stornierter Belege.
|
||||
- [KONTEXT] Klassenname InvoiceZugferdBL (referenziert, nicht im Detail gelesen) - Begründung: Bestätigt Existenz einer dedizierten ZUGFeRD-Komponente; Implementierungsdetails nicht verifiziert.
|
||||
Prüfidee: Rechnung mit aktivierter ZUGFeRD-Einstellung erzeugen → resultierendes PDF enthält eingebettetes XML gemäß ZUGFeRD-Schema.
|
||||
Tracelinks: SyRS-014, StRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-012
|
||||
Titel: Digitale Signatur von Dokumenten (C-Sign)
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Systemadministrator, Vertrieb/Innendienst, Web-Portal-Kunde/anonymer Angebotsempfänger
|
||||
Vorbedingung: Ein Signaturzertifikat ist im System hinterlegt bzw. eine Signatur-Interaktion im Kundenportal ist vorgesehen.
|
||||
Fakt: PdfSigningBL verwaltet Zertifikat, TSA-Zeitstempeldienst-Zugangsdaten und signiert PDF-Dokumente (DevExpress.Office.DigitalSignatures/Tsp); sensible Werte (Zertifikat, Passwörter) werden vor der Speicherung AES-verschlüsselt. Ergänzend existiert im Kundenportal eine browserbasierte Unterschriftenfunktion (IsolatedSignaturePad.razor, DocumentSigningPage.razor).
|
||||
Aussage: Das System soll Dokumente serverseitig mit einem hinterlegten Zertifikat (optional mit Zeitstempel) digital signieren können und zusätzlich eine browserbasierte handschriftliche Unterschrift im Kundenportal ermöglichen.
|
||||
Ergebnis: Signierte PDF-Dokumente sind mit einer nachprüfbaren digitalen Signatur versehen; Zugangsdaten zum Signaturdienst liegen nicht im Klartext in der Datenbank.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs (Z. 1-90) - Begründung: Verwaltung von Zertifikat/TSA-Konfiguration inkl. AES-Verschlüsselung und Rechteprüfung (Administration.SETTINGS) beim Speichern.
|
||||
- [SEKUNDÄR] src/nexus/CentronNexus/DocumentSigning/DocumentSigningPage.razor, IsolatedSignaturePad.razor - Begründung: UI-Komponenten für browserseitige Unterschrift (Namen/Struktur bestätigen Funktion, Implementierungsdetails nicht vollständig gelesen).
|
||||
- [KONTEXT] CentronObjectKindNumeric.DocumentSigning=7600133 / DocumentSigningCustomerReceipts=7600146 - Begründung: Eigene Objektart bestätigt, dass Signatur als first-class Domänenkonzept modelliert ist.
|
||||
Prüfidee: Signatureinstellungen (Zertifikat/TSA) werden von einem Benutzer ohne Administration.SETTINGS-Recht abgelehnt gespeichert; ein signiertes PDF weist eine gültige, prüfbare Signatur auf.
|
||||
Tracelinks: SyRS-015, StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-013
|
||||
Titel: Kundenseitige Angebotsannahme über Web-Portal ohne Login
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Anonymer Angebotsempfänger
|
||||
Vorbedingung: Ein Angebot wurde als Web-Angebot freigegeben; der Empfänger besitzt den zugehörigen Link.
|
||||
Fakt: Die Blazor-Route "/weboffer/{Token}" (WebReceiptOverview.razor) verwendet ein leeres Layout ohne Login-Zwang; der Beleg wird über einen Token statt über Benutzeranmeldung referenziert, inkl. PDF-Vorschau-Link und mandantenspezifischem Branding/Logo.
|
||||
Aussage: Das System soll es ermöglichen, ein Angebot über einen individuellen Link (Token) ohne vorherige Registrierung oder Anmeldung online einsehbar und (fachlich anzunehmen) zu machen.
|
||||
Ergebnis: Der Empfänger des Links kann das Angebot direkt im Browser einsehen, als PDF vorschauen und (laut Modulname "Acceptance"/"C-Sign") elektronisch bestätigen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor (Z. 1-90) - Begründung: Enthält Routendefinition, Login-freies Layout und Beleg-/Branding-Darstellung.
|
||||
- [KONTEXT] Commit 89ccfd650d "Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)" - Begründung: Bestätigt fachlichen Zusammenhang zwischen WebOffer und Annahme-/Signaturprozess (Change-Historie).
|
||||
Prüfidee: Aufruf der URL .../weboffer/{gültigesToken} ohne vorherige Anmeldung zeigt das zugehörige Angebot inklusive Mandantenbranding an; ein ungültiges/abgelaufenes Token verweigert den Zugriff (Detail-Mechanismus nicht verifiziert, siehe Hypothesen.md).
|
||||
Tracelinks: SyRS-016, StRS-012, StRS-020
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-014
|
||||
Titel: DSGVO-konforme Datenbereinigung und Löschung personenbezogener Daten
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Datenschutzbeauftragter, Systemadministrator
|
||||
Vorbedingung: Personenbezogene Daten (Kunden, Ansprechpartner, CRM-Aktivitäten) sind über die gesetzliche/betriebliche Aufbewahrungsfrist hinaus gespeichert.
|
||||
Fakt: DataSecurityBL bietet Statistikfunktionen zu Löschkandidaten (alte CRM-Aktivitäten, alte Belege, inaktive Kunden), gated durch Recht ACCESS_CLEANUP_DATABASE und Feature-Flag IsDsgvoDatabaseCleanupAvailable; die eigentliche Ausführungsmethode DataSecurityExecuteCleanUp (Z. 64-70) prüft nur Rechte, enthält aber keine Lösch-/Anonymisierungslogik. Für Ansprechpartner existiert separat ein textueller Lösch-Platzhalter ("DSGVO: Auf Anfrage gelöscht.").
|
||||
Aussage: Das System soll autorisierten Benutzern ermöglichen, personenbezogene Daten identifizieren und DSGVO-konform bereinigen bzw. löschen/anonymisieren zu können.
|
||||
Ergebnis: Zur Identifikation von Löschkandidaten stehen Statistikfunktionen bereit; für Ansprechpartner ist eine Einzel-Löschfunktion (Anonymisierung durch Platzhaltertext) vorhanden. Die massenhafte automatisierte Datenbereinigung ist im untersuchten Codestand nicht vollständig implementiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, GetDataSecurityCleanUpStats (Z. 34-62), DataSecurityExecuteCleanUp (Z. 64-70) - Begründung: Zeigt sowohl die vorhandene Rechteprüfung als auch die fehlende Umsetzungslogik der eigentlichen Bereinigung.
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs (Z. 26-27), Konstanten DsgvoDeletedContactMessage(WithEmployeeInfo) - Begründung: Belegt vorhandene Einzel-Anonymisierungsfunktion für Ansprechpartner (Text-Platzhalter statt Hartlöschung).
|
||||
Prüfidee: Aufruf von DataSecurityExecuteCleanUp mit gültigen Rechten führt zu keiner beobachtbaren Datenänderung (Abgleich Datenbestand vor/nach Aufruf) → bestätigt Stub-Charakter.
|
||||
Tracelinks: SyRS-017, SyRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-015
|
||||
Titel: Ticket-/Helpdesk-Verwaltung mit konfigurierbaren Status
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Helpdesk-/Servicemitarbeiter, Web-Portal-Kunde
|
||||
Vorbedingung: Ein Kundenanliegen (Ticket) wird erfasst.
|
||||
Fakt: Die Helpdesk-Entität modelliert Kategorie-Hierarchie (Haupt-/zwei Unterkategorien), Priorität, Lösung, Status, Typ, mehrere Bearbeiter (Editors), Eskalationsstufe, Bearbeitungssperre (LockUserName), Eltern-Ticket-Referenz und Sichtbarkeitssteuerung (IsOnlyInternalVisible); der Status selbst ist keine feste Enumeration, sondern konfigurierbare Stammdaten (HelpdeskStateBase).
|
||||
Aussage: Das System soll Kundenanliegen als Tickets mit frei konfigurierbaren Status, Kategorien und Prioritäten verwalten, eine Eskalationssteuerung sowie eine Sperre gegen gleichzeitige Bearbeitung durch mehrere Mitarbeiter bieten und einzelne Ticketinhalte wahlweise intern-only kennzeichnen können.
|
||||
Ergebnis: Tickets durchlaufen kundenspezifisch definierbare Status; nur ein Bearbeiter kann ein gesperrtes Ticket gleichzeitig ändern; als intern markierte Inhalte sind für den Kunden nicht sichtbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs (Z. 1-144) - Begründung: Vollständiges Datenmodell mit allen genannten Feldern.
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskStateBase.cs - Begründung: Bestätigt, dass Status als Stammdaten (nicht Code-Enum) modelliert ist – im Gegensatz zu ReceiptState.
|
||||
Prüfidee: Ein Ticket mit IsOnlyInternalVisible=true zeigt den betreffenden Inhalt im Kundenportal nicht an; ein gesperrtes Ticket (LockUserName gesetzt) kann von einem zweiten Bearbeiter nicht gleichzeitig verändert werden (UI-seitige Prüfung, Detailmechanismus nicht vollständig verifiziert).
|
||||
Tracelinks: SyRS-019, SyRS-020
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-016
|
||||
Titel: Zeitbasierte Leistungsabrechnung (Timer-Fakturierung)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Helpdesk-/Servicemitarbeiter, Buchhaltung/Controlling
|
||||
Vorbedingung: Arbeitszeiten wurden auf einem Ticket/Vorgang erfasst (HelpdeskTimer) und sollen fakturiert werden.
|
||||
Fakt: Der TimerBilling-Assistent erzeugt aus erfassten Zeiten wahlweise Rechnungen oder Lieferscheine; das Fakturierungsdatum ("BillingDate") ist nur änderbar, wenn eine entsprechende, belegtypabhängige Berechtigungs-/Konfigurationseinstellung (CanChangeDateInInvoices/CanChangeDateInDeliveryLists) aktiv ist, sonst wird ein erläuternder Hinweistext angezeigt.
|
||||
Aussage: Das System soll erfasste Zeiten gebündelt in Rechnungen oder Lieferscheine überführen können und dabei die Änderbarkeit des Fakturierungsdatums von einer zentralen Berechtigungs-/Konfigurationseinstellung abhängig machen.
|
||||
Ergebnis: Benutzer ohne die entsprechende Berechtigung sehen das Fakturierungsdatum als nicht änderbar mit erklärendem Hinweistext; berechtigte Benutzer können das Datum frei setzen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs (UpdateBillingDateIsEnabled, Diff aus Commit baa9e7bd9b) - Begründung: Tatsächliche UI-Logik, die die Einstellung auswertet und den Hinweistext dynamisch erzeugt.
|
||||
- [KONTEXT] Commit baa9e7bd9b "feat: added rights check for editing invoice or delivery list date in the settings of timer billing." - Begründung: Bestätigt fachliche Motivation (Rechteprüfung) der Änderung.
|
||||
Prüfidee: Benutzer ohne CanChangeDateInInvoices-Einstellung öffnet die Timer-Fakturierungs-Einstellungen für eine Rechnung → BillingDate-Feld ist deaktiviert, Hinweistext "Sie besitzen nicht das Recht ... Datum der Rechnung nach neuer Version / bei Neuanlage ändern" wird angezeigt.
|
||||
Tracelinks: SyRS-021, StRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-017
|
||||
Titel: Nachvollziehbare Einkaufspreisführung im Lager
|
||||
Ebene: StRS
|
||||
Typ: Daten
|
||||
Akteur: Lager-/Einkaufsmitarbeiter
|
||||
Vorbedingung: Ein Wareneingang (Bestellung/Wareneingangsbeleg) wird auf einen Artikel gebucht.
|
||||
Fakt: UpdateArticlePurchasePriceThroughStockBooking historisiert den Einkaufspreis: der bisher "aktuelle" Rohpreis (RawEk1) wird vor dem Überschreiben nach RawEk2 verschoben (inkl. Datum und Quellbeleg-Referenz), bevor der neue Preis aus der Buchung übernommen wird; Haupt- und Nebenlager werden unterschiedlich behandelt.
|
||||
Aussage: Das System soll bei jeder Einkaufspreis-relevanten Lagerbuchung den vorherigen Einkaufspreis inklusive Quellbeleg und Datum revisionssicher als Vorwert erhalten, bevor der neue Preis übernommen wird.
|
||||
Ergebnis: Zu jedem Artikel sind mindestens die zwei letzten Einkaufspreise mit Quellbeleg-Referenz nachvollziehbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, UpdateArticlePurchasePriceThroughStockBooking (Z. 3602-3652 ff.) - Begründung: Konkrete SQL-Update-Logik, die RawEk1→RawEk2 verschiebt und RawEk1 neu setzt inkl. ObjectI3D/ObjectKind-Referenz auf den auslösenden Beleg.
|
||||
Prüfidee: Zwei aufeinanderfolgende Wareneingangsbuchungen mit unterschiedlichem Preis auf denselben Artikel → RawEk2 entspricht nach der zweiten Buchung dem Preis der ersten Buchung.
|
||||
Tracelinks: SyRS-022
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-018
|
||||
Titel: Modulare, lizenzgesteuerte Funktionsfreischaltung
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional
|
||||
Akteur: c-entron (Hersteller/Lizenzgeber), Systemadministrator
|
||||
Vorbedingung: Ein Mandant hat eine bestimmte Kombination von Modullizenzen erworben.
|
||||
Fakt: LicenseGuids.cs definiert einen umfangreichen Katalog einzeln lizenzierbarer Module (u. a. Abrechnung, Administration, CRM, Buchhaltung/Finanzen, Controlling/Analytics, Einkauf, Helpdesk, Logistik, Verträge) sowohl als klassische Einzellizenzen als auch im neueren Subscription-Modell (CentronSubscription); CentronHostedAuthorization prüft eine spezifische Lizenz (CentronInternal) zur Laufzeit über LicenseManager, bevor bestimmte API-Endpunkte zugänglich sind.
|
||||
Aussage: Das System soll seine Funktionsbereiche in einzeln lizenzierbare Module gliedern und die Verfügbarkeit von Funktionen (UI wie API) zur Laufzeit anhand der für den Mandanten aktivierten Lizenzen steuern.
|
||||
Ergebnis: Nicht lizenzierte Module/Endpunkte sind für den Mandanten nicht nutzbar bzw. nicht erreichbar, unabhängig von den Benutzerrechten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs (vollständige Datei) - Begründung: Erschöpfender, nach Fachmodulen gegliederter Lizenzkatalog, aktiv im Code referenziert.
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/CentronHostedAuthorization.cs (Z. 8-25) - Begründung: Tatsächliche Laufzeitprüfung einer Lizenz als Autorisierungs-Policy.
|
||||
Prüfidee: Ein Mandant ohne Lizenz "CentronInternal" erhält bei Aufruf eines mit der Policy "CentronHosted" geschützten Endpunkts keinen Zugriff, unabhängig von individuellen Benutzerrechten.
|
||||
Tracelinks: SyRS-023
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-019
|
||||
Titel: Absicherung von System- und API-Zugängen
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Interner Benutzer, Externes System (CentronNexus)
|
||||
Vorbedingung: Ein Client (WPF-Anwendung, externe Integration, CentronNexus) möchte auf die zentrale API zugreifen.
|
||||
Fakt: Der API-Host kombiniert mehrere Authentifizierungsschemata: ein proprietäres "Ticket"-Schema für den Desktop-Client, JWT-Bearer-Tokens mit vollständiger Validierung (Issuer, Audience, Lifetime, Signatur, Replay-Schutz) für moderne Clients, sowie eine "SecretKey"-Policy speziell für die Verbindung zu CentronNexus.
|
||||
Aussage: Das System soll je nach Client-Typ ein passendes, jeweils vollständig serverseitig validiertes Authentifizierungsverfahren verlangen und den Zugriff ohne gültige Authentifizierung verweigern.
|
||||
Ergebnis: Anfragen ohne gültiges Ticket, gültigen JWT bzw. gültigen SecretKey werden von der API abgelehnt (401), bevor fachliche Logik oder Rechteprüfung überhaupt greift.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs (Z. 183-222) - Begründung: Zentrale, tatsächlich aktive Konfiguration aller drei Authentifizierungsmechanismen inkl. strenger JWT-Validierungsparameter.
|
||||
Prüfidee: Aufruf eines geschützten Endpunkts ohne jegliches Authentifizierungsmerkmal → HTTP 401; Aufruf mit abgelaufenem JWT → 401 (ValidateLifetime=true).
|
||||
Tracelinks: SyRS-024, SyRS-025, StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-020
|
||||
Titel: Mandantenspezifisches Branding im Webportal
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional
|
||||
Akteur: Web-Portal-Kunde, anonymer Angebotsempfänger, Systemadministrator
|
||||
Vorbedingung: Ein Mandant nutzt das Kundenportal (CentronNexus) unter eigenem Erscheinungsbild.
|
||||
Fakt: WebReceiptOverview.razor bindet ein mandantenspezifisches Logo (Receipt.MandatorImage) sowie eine über IOptionsSnapshot<BrandingConfig> injizierte Konfiguration ein.
|
||||
Aussage: Das System soll es ermöglichen, das Kundenportal pro Mandant mit eigenem Erscheinungsbild (mindestens Logo) auszuliefern.
|
||||
Ergebnis: Kunden unterschiedlicher Mandanten sehen im Web-Angebot/-Portal jeweils das Branding ihres Vertragspartners.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor (Z. 12, 27, 38-42) - Begründung: Konkrete Einbindung von BrandingConfig und MandatorImage in der Darstellung.
|
||||
Prüfidee: Zwei Mandanten mit unterschiedlich konfiguriertem Logo erzeugen sichtbar unterschiedliche Web-Angebots-Seiten.
|
||||
Tracelinks: SyRS-027, StRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Ergänzende, migrationsrelevante Beobachtung (kein eigenständiges StRS, siehe Analysebericht)
|
||||
|
||||
Neben dem WPF-Desktopclient existiert bereits eine separate ASP.NET-Blazor-Webanwendung "CentronNexus" (460 .razor-Dateien) mit den Modulen WebOffer, WebCart, DocumentSigning, ServiceBoard und ProductionOrderManagement. Für eine Web-/SaaS-Neuimplementierung ist dies als bereits vorhandener, teilweise produktiver Modernisierungsansatz zu werten und nicht als "grüne Wiese" zu behandeln (siehe Analysebericht.md, Abschnitt Selbstbewertung).
|
||||
+510
@@ -0,0 +1,510 @@
|
||||
# Software Requirements Specification (SwRS)
|
||||
|
||||
Ebene: Komponenten, Datenmodelle, software-interne Regeln. Jede Anforderung referenziert die zugehörige SyRS-Anforderung (Backward-Traceability) gemäß Auftrag.
|
||||
|
||||
```
|
||||
ID: SwRS-001
|
||||
Titel: Klasse AppRightsBL als zentrale Rechte-Fassade mit Session-Cache
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente AppRightsBL
|
||||
Vorbedingung: Eine DAOSession ist initialisiert.
|
||||
Fakt: AppRightsBL : BaseBL kapselt alle Lese-/Schreiboperationen auf AppRight/AppGroup/AppGroupRightAssignment/AppUserMember; HasUserRight (Z. 644-649) nutzt Session.Advanced.Cache.GetOrAdd mit Schlüssel "AllRightsFromAppUser{appUserI3D}".
|
||||
Aussage: Die Komponente AppRightsBL soll als alleinige Zugriffsschicht für Rechteoperationen fungieren und Ergebnisse rechteabfragender Methoden pro Benutzer innerhalb der Session zwischenspeichern.
|
||||
Ergebnis: Andere Komponenten rufen ausschließlich AppRightsBL/HasUserRight (bzw. dessen Extension-Methode auf AppUser) auf, nie direkten SQL-Zugriff auf Sichtrus/Sichmemb.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 25-37, 644-649) - Begründung: Klassendefinition und Cache-Nutzung im produktiven Prüfpfad.
|
||||
Prüfidee: Codeanalyse: keine weiteren Vorkommen von direktem SQL-Zugriff auf Sichtrus/Sichmemb außerhalb AppRightsBL im Backend-Quellcode.
|
||||
Tracelinks: SyRS-001, SyRS-029
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-002
|
||||
Titel: SQL-Abfrage GetAllAppRightsFromUser (Sichtrus/Sichmemb-JOIN)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente AppRightsBL
|
||||
Vorbedingung: Cache-Miss für den angefragten Benutzer.
|
||||
Fakt: GetAllAppRightsFromUser (Z. 651-664) führt exakt `SELECT st.Recht AS ID FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D` aus.
|
||||
Aussage: Die Komponente soll bei fehlendem Cache-Eintrag genau eine SQL-Abfrage ausführen, die alle Recht-IDs eines Benutzers über dessen Gruppenmitgliedschaften ermittelt.
|
||||
Ergebnis: Rückgabe einer vollständigen, ungefilterten Liste aller Recht-IDs, die dem Benutzer über beliebige seiner Gruppen zustehen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 651-664) - Begründung: Vollständiges SQL-Statement im Code sichtbar.
|
||||
Prüfidee: Benutzer in zwei Gruppen mit überschneidenden Rechten → Ergebnisliste enthält jedes Recht nur gemäß SQL-JOIN-Semantik (Duplikate möglich, da kein DISTINCT im Statement).
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-003
|
||||
Titel: Klasse UserRightAuthorizationFilter (IAuthorizationFilter)
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente ASP.NET-Core-Pipeline
|
||||
Vorbedingung: Eine Action ist mit [AuthorizeUserRight(rightId)] annotiert.
|
||||
Fakt: OnAuthorization (Z. 38-56) setzt context.Result = UnauthorizedResult(), wenn kein User.GetCurrent(), sonst context.Result = ForbidResult(), wenn !currentUser.HasUserRight(rightId).
|
||||
Aussage: Die Komponente soll als ASP.NET-Core-IAuthorizationFilter vor jeder annotierten Action ausgeführt werden und Requests ohne gültige Authentifizierung mit 401, ohne ausreichendes Recht mit 403 beantworten.
|
||||
Ergebnis: Die Action-Methode wird nicht erreicht, wenn eine der beiden Bedingungen fehlschlägt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs (Z. 29-56) - Begründung: Vollständige Filterklasse.
|
||||
Prüfidee: Unit-Test des Filters mit gemocktem HttpContext ohne User → context.Result ist UnauthorizedResult; mit User ohne Recht → ForbidResult.
|
||||
Tracelinks: SyRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-004
|
||||
Titel: Methode CanUserViewReceipt mit Fail-Fast für WebAccounts
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente ReceiptBL
|
||||
Vorbedingung: Ein Aufrufer prüft, ob ein LoggedInUser einen bestimmten Beleg einsehen darf.
|
||||
Fakt: Erste Anweisung im Methodenkörper (Z. 10299-10302) prüft loggedInUser.IsWebAccountLogin und liefert sofort Result.AsError mit MessageCode RightCheckFailed, bevor _specificLogics.Execute(...) für die eigentliche Rechteprüfung überhaupt aufgerufen wird.
|
||||
Aussage: Die Methode CanUserViewReceipt soll die WebAccount-Sperre als ersten Kontrollfluss-Zweig implementieren (Fail-Fast), sodass keine weitere Rechte- oder Fachlogik für WebAccounts ausgeführt wird.
|
||||
Ergebnis: Rechenzeit für nachgelagerte Prüfungen wird für WebAccounts eingespart; das Verhalten ist unabhängig von eventuell fehlerhaft vergebenen internen Rechten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 10297-10311) - Begründung: Vollständige Methode mit Reihenfolge der Prüfungen.
|
||||
Prüfidee: Statischer Codepfad-Test: bei IsWebAccountLogin==true wird _specificLogics.Execute nicht erreicht (Branch-Coverage).
|
||||
Tracelinks: SyRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-005
|
||||
Titel: Methode CanUserEditReceipt mit zweistufiger Prüfsequenz
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente ReceiptBL
|
||||
Vorbedingung: Ein Aufrufer prüft Bearbeitungsrecht für receiptKind/appUser/receiptBranchI3D.
|
||||
Fakt: Erst wird `_specificLogics.Execute(receiptKind, f => f.HasRightToEditReceipt(appUser))` geprüft (Z. 10277-10282), danach unabhängig `HasRightToEditReceiptOnlyOwnBranch` + `BranchBL.IsBranchEqual` (Z. 10284-10292); beide nutzen das Strategy-Pattern `_specificLogics.Execute(receiptKind, ...)` zur belegartspezifischen Delegation.
|
||||
Aussage: Die Methode CanUserEditReceipt soll die belegartspezifische Fachlogik über ein Strategy-Objekt je ReceiptKind delegieren und die Filialprüfung als zweiten, unabhängigen Schritt nach der allgemeinen Rechteprüfung ausführen.
|
||||
Ergebnis: Neue Belegarten können ihre Rechteprüfung implementieren, ohne CanUserEditReceipt selbst zu ändern (Open/Closed-Prinzip über Strategy-Pattern).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 10272-10295) - Begründung: Vollständige Methode inkl. Strategy-Aufrufe.
|
||||
Prüfidee: Neue Testimplementierung von HasRightToEditReceipt für eine fiktive Belegart wird korrekt von CanUserEditReceipt verwendet, ohne dass die Methode selbst angepasst werden muss.
|
||||
Tracelinks: SyRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-006
|
||||
Titel: Konstante Whitelist GetAssignableAdminRightI3Ds (38 Recht-IDs)
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente AppRightsBL
|
||||
Vorbedingung: Eine Rechteänderung an der Administratorengruppe wird angefordert.
|
||||
Fakt: Die private Methode (Z. 714-759) liefert eine hart kodierte Liste von 38 int-Literalen mit Inline-Kommentaren (z. B. 20400149 "Angebote anzeigen - nur Eigene"); SaveAndAssignGroupToRight/RemoveAssignGroupToRight prüfen `changeableRights.Contains(selectedRight.I3D)`.
|
||||
Aussage: Die Komponente soll Änderungen an der Administratorengruppe ausschließlich für Rechte zulassen, deren I3D in dieser statisch definierten Liste enthalten ist.
|
||||
Ergebnis: Rechte außerhalb der Liste (z. B. Rechteverwaltung selbst, Systemeinstellungen) können der Administratorengruppe nicht über diesen Pfad entzogen werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 714-759, Aufrufstellen Z. 266-271, 284-289) - Begründung: Vollständige Liste und beide Verwendungsstellen.
|
||||
Prüfidee: Aufruf von RemoveAssignGroupToRight mit einer nicht in der Liste enthaltenen Recht-I3D und der Administratorengruppe → Rückgabewert false, keine Datenbankänderung.
|
||||
Tracelinks: SyRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-007
|
||||
Titel: Protokollklasse AppRightLog mit Kind-Enum AppRightLogKind
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente AppRightsBL, Entität AppRightLog
|
||||
Vorbedingung: Eine änderende Rechte-/Gruppenoperation wurde erfolgreich ausgeführt.
|
||||
Fakt: WriteBaseLog (Z. 762-781) erzeugt einen AppRightLog mit CreatedByI3D (aus appUser.Employee.I3D), CreatedDate, CreatedVersion (aus AssemblyLogic), Kind (Enum AppRightLogKind), Object, State=true, Description; sieben spezialisierte Write*-Methoden (Z. 783-857) rufen WriteBaseLog mit vorformatiertem deutschen Beschreibungstext auf.
|
||||
Aussage: Die Komponente soll für jede der sieben unterstützten Änderungsarten (AddRightToGroup, RemoveRightFromGroup, CreateGroup, DeleteGroup, AddUserToGroup, RemoveUserFromGroup, CopyGroup) einen strukturell identischen, aber inhaltlich spezifischen Log-Eintrag über eine gemeinsame Basismethode erzeugen.
|
||||
Ergebnis: GetAllAppRightLogs liefert eine einheitlich strukturierte, nach CreatedDate absteigend sortierte Änderungshistorie.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 558-561, 761-858) - Begründung: Abruf- und Schreibpfad vollständig im Code.
|
||||
Prüfidee: Für jede der sieben Operationen existiert ein Test, der nach Ausführung einen AppRightLog mit korrektem Kind-Wert erwartet.
|
||||
Tracelinks: SyRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-008
|
||||
Titel: Abstrakte Klasse ReceiptBase mit Positions-Vertrag
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente Centron.Entities
|
||||
Vorbedingung: Eine konkrete Belegklasse (z. B. Offer, Order, Invoice) wird definiert.
|
||||
Fakt: ReceiptBase deklariert vier abstrakte Members (ReceiptKind als CentronObjectKindNumeric-Property, GetReceiptItems/SetReceiptItems/AddItem/RemoveItem) sowie konkrete gemeinsame Felder (u. a. Number, Date, Version, State, ConcurrencyControlGuid, IsTemplate als berechnete Property `Number < 0`).
|
||||
Aussage: Die Basisklasse ReceiptBase soll für jede Unterklasse die Implementierung einer belegartspezifischen Positionsverwaltung erzwingen, während der Belegkern (Nummer, Datum, Status, Concurrency) einheitlich vererbt wird.
|
||||
Ergebnis: Generischer Code (z. B. NumberGroupBL, ReceiptBL-Kernlogik) kann gegen den Typ IReceiptBase/ReceiptBase programmieren, ohne die konkrete Belegart zu kennen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs (vollständige Datei) - Begründung: Direkte Klassendefinition.
|
||||
Prüfidee: Compile-Test: jede konkrete Receipt-Unterklasse implementiert alle vier abstrakten Members (Compiler erzwingt dies bereits strukturell).
|
||||
Tracelinks: SyRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-009
|
||||
Titel: Methode GetReceiptForwardedInto mit Statusfilter
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ReceiptBL
|
||||
Vorbedingung: Ein Beleg mit ReceiptKind und I3D wird auf Weiterführung geprüft.
|
||||
Fakt: Die Methode filtert Folgebelege über `f.OtherReceiptState != ReceiptState.Canceled` (Z. 9946), sodass stornierte Folgebelege bei der Prüfung entfernbarer Positionen ignoriert werden (Z. 9944-9946, removedPositionsThatCouldNotBeRemoved).
|
||||
Aussage: Die Methode soll bei der Ermittlung, ob eine Belegposition bereits "verbraucht" ist, ausschließlich nicht-stornierte Folgebelege berücksichtigen.
|
||||
Ergebnis: Eine Position, die nur in einem zwischenzeitlich stornierten Folgebeleg verwendet wurde, gilt weiterhin als entfernbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 9938-9946) - Begründung: Konkreter Filterausdruck im Code.
|
||||
Prüfidee: Position in storniertem Folgebeleg → Entfernung aus Ursprungsbeleg wird nicht blockiert; Position in aktivem Folgebeleg → wird blockiert.
|
||||
Tracelinks: SyRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-010
|
||||
Titel: Methode UpdateReceiptIsPaid mit Status- und Alternativrechtsprüfung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Komponente ReceiptBL
|
||||
Vorbedingung: isPaid oder paidFC soll für einen Beleg gesetzt werden.
|
||||
Fakt: Reihenfolge im Code (Z. 4902-4944): (1) Typprüfung IReceiptWithPayment/IReceiptCreditVoucher, (2) CanUserEditReceipt mit Sonderbehandlung RightCheckFailed→INCOMING_PAYMENT_TRANSACTIONS, (3) State==Canceled-Sperre, (4) ConcurrencyControlGuid-Vergleich, (5) tatsächliche Statusänderung (newState = isPaid ? Completed : Active).
|
||||
Aussage: Die Methode UpdateReceiptIsPaid soll Typ-, Rechte-, Status- und Concurrency-Prüfung in dieser festen Reihenfolge ausführen, bevor der Zahlungsstatus des Belegs geändert wird.
|
||||
Ergebnis: Jede der vier Vorprüfungen kann die Operation unabhängig voneinander mit spezifischer Fehlermeldung/MessageCode ablehnen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 4902-4944) - Begründung: Vollständige Methode mit allen vier Prüfschritten.
|
||||
Prüfidee: Vier getrennte Testfälle, je einer pro Prüfschritt, der isoliert zum Fehlschlagen der Methode führt.
|
||||
Tracelinks: SyRS-009, SyRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-011
|
||||
Titel: Methode FindNextNumber mit iterativer Kollisionsprüfung
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente NumberGroupBL
|
||||
Vorbedingung: Ein NumberGroup-Objekt mit Current/Interval ist geladen.
|
||||
Fakt: `counter = current + interval`; While-Schleife führt `SELECT COUNT(*) FROM {tableName} WHERE {fieldName} = {counter}` (dynamisch per numberGroup.GetTableName()/GetFieldName()/GetCompareAsStrings()) aus und erhöht counter um interval, bis COUNT=0; Sonderfälle Customer/Supplier prüfen zusätzlich gegen dbo.Kunden/dbo.Kreditor (Z. 114-131).
|
||||
Aussage: Die Methode FindNextNumber soll ausgehend vom letzten vergebenen Wert iterativ die nächste tatsächlich freie (nicht in der Zieltabelle vorkommende) Nummer ermitteln.
|
||||
Ergebnis: Die zurückgegebene Nummer ist zum Prüfzeitpunkt garantiert nicht in der Zieltabelle (und bei Customer/Supplier zusätzlich nicht in Kunden/Kreditor) vorhanden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs (Z. 94-134) - Begründung: Vollständige Methode inkl. Sonderfallbehandlung.
|
||||
Prüfidee: Manuelles Vorbelegen der Zieltabelle mit der rechnerisch nächsten Nummer → FindNextNumber überspringt diese und liefert die übernächste.
|
||||
Tracelinks: SyRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-012
|
||||
Titel: Methode GetNextNumber mit bedingtem Update und Retry-Schleife
|
||||
Ebene: SwRS
|
||||
Typ: Daten (Zuverlässigkeit)
|
||||
Akteur: Komponente NumberGroupBL
|
||||
Vorbedingung: updateDatabase=true; mehrere Prozesse greifen potenziell gleichzeitig auf dieselbe NumberGroup zu.
|
||||
Fakt: `while(true)`-Schleife (Z. 67-91): Refresh des numberGroupObject, FindNextNumber, dann bedingtes Update `WHERE I3D=... AND Current=...` mit `.Set(Current, nextNumber)`; nur bei rowCountChanged==1 wird das Ergebnis übernommen und zurückgegeben, sonst wiederholt sich die Schleife komplett (inkl. erneutem Refresh und erneuter Kollisionsprüfung).
|
||||
Aussage: Die Methode GetNextNumber soll die Nummernreservierung als bedingtes Compare-and-Swap-Update implementieren und bei Konflikt (paralleler Vergabe) den gesamten Ermittlungsvorgang wiederholen statt die verlorene Nummer erneut zu versuchen.
|
||||
Ergebnis: Auch bei hoher Nebenläufigkeit wird niemals dieselbe Nummer zweimal reserviert; im Konfliktfall verlängert sich lediglich die Ausführungszeit (kein Datenverlust).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs (Z. 62-92) - Begründung: Vollständige Retry-Logik mit Kommentar zur Absicht ("safety measure, should someone in the meantime reserve this number").
|
||||
Prüfidee: Zwei simulierte parallele Aufrufe (z. B. über zwei Threads/Sessions) auf dieselbe NumberGroup → beide terminieren erfolgreich mit unterschiedlichem Ergebnis; kein Deadlock, keine Endlosschleife bei realistischer Last.
|
||||
Tracelinks: SyRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-013
|
||||
Titel: Methoden CreateNumberGroups und UpdateReceiptNumber (Mandant/Filiale/Vorlage)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente NumberGroupBL, ReceiptBL
|
||||
Vorbedingung: Ein neuer Mandant/eine neue Filiale wird angelegt bzw. ein Beleg wird gespeichert.
|
||||
Fakt: CreateNumberGroups (Z. 154-187) erzeugt für jeden NumberGroupEnum-Wert (außer Contract/ClickContract, siehe GetNumberGroupEnumsToCreate Z. 189-197) ein NumberGroup-Objekt je (MandantI3D, BranchI3D); UpdateReceiptNumber (ReceiptBL.cs Z. 7265-7285) prüft vorab, ob der Kunde des Belegs der konfigurierten Vorlagen-Kundennummer entspricht, und verzweigt dann auf `_receiptTemplateBL.GetNextReceiptTemplateNumber` statt auf `_numberGroupBL.GetNextNumber`.
|
||||
Aussage: Die Komponenten sollen Nummernkreise strukturell je Mandant/Filiale und Belegart trennen und Belegvorlagen über einen komplett separaten Nummerierungspfad führen, der nicht mit dem regulären Nummernkreis interferiert.
|
||||
Ergebnis: Vorlagenbelege (erkennbar an negativer Nummer, vgl. IsTemplate) verbrauchen keine Nummern aus dem produktiven Nummernkreis.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs (Z. 154-197) - Begründung: Vollständige Erzeugungslogik.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 7265-7285, 7280) - Begründung: Konkrete Verzweigung auf Vorlagen-Nummernkreis.
|
||||
Prüfidee: Speichern eines Belegs für den konfigurierten Vorlagen-Kunden → erzeugte Nummer stammt nachweislich nicht aus derselben Zählersequenz wie reguläre Belege desselben Typs.
|
||||
Tracelinks: SyRS-011
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-014
|
||||
Titel: Versionsvalidierung in SaveReceipt (isFirstVersion/isCurrentVersion/isNextVersion)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ReceiptBL
|
||||
Vorbedingung: Ein Beleg mit gesetzter Version wird gespeichert.
|
||||
Fakt: Drei Boolean-Ausdrücke (Z. 3569-3571) prüfen: erste Version (kein Vorgänger, Version==1), aktuelle Version (Version entspricht Vorgänger-Version) oder nächste Version (Version==Vorgänger-Version+1); nur wenn mindestens eine zutrifft, wird fortgefahren, sonst Fehlermeldung "Der Beleg hat keine gültige Versionsnummer." (Z. 3573-3578).
|
||||
Aussage: Die Methode SaveReceipt soll jede eingehende Versionsnummer gegen drei explizit erlaubte Fälle validieren und jede andere Versionsnummer (z. B. übersprungene oder negative Sprünge) als Fachfehler ablehnen.
|
||||
Ergebnis: Die Versionskette eines Belegs ist immer lückenlos nachvollziehbar (1, 2, 3, ... oder Überschreiben der aktuellen Version).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 3557-3578) - Begründung: Vollständige Validierungslogik mit den drei benannten Fällen.
|
||||
Prüfidee: Speichern eines Belegs mit Version=Vorgänger+2 → Fehlermeldung "keine gültige Versionsnummer"; Version=Vorgänger (Überschreiben) und Version=Vorgänger+1 → jeweils erfolgreich.
|
||||
Tracelinks: SyRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-015
|
||||
Titel: Bedingungsblock zur ZUGFeRD-PDF-Erzeugung im Report-Rendering
|
||||
Ebene: SwRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Komponente ReceiptBL, InvoiceZugferdBL
|
||||
Vorbedingung: Ein Belegreport (PDF) wird für eine Rechnung/Gutschrift erzeugt.
|
||||
Fakt: Zusammengesetzte Bedingung (Z. 3272-3274): `(receiptKind==InvoiceClass || receiptKind==CreditVoucherClass) && (new InvoiceZugferdBL(Session).IsZugferdEnabled() || GetLocalZUGFeRDSetting(receipt)==true) && receipt.State != ReceiptState.Canceled`.
|
||||
Aussage: Der Bedingungsblock soll alle drei Kriterien (Belegart, Aktivierungsquelle global-oder-lokal, Nicht-Storniert-Status) konjunktiv (UND) verknüpfen, bevor die ZUGFeRD-Erzeugung ausgelöst wird.
|
||||
Ergebnis: Eine Deaktivierung auf globaler Ebene kann durch eine aktivierte lokale Beleg-Einstellung überschrieben werden (ODER-Verknüpfung innerhalb der Aktivierungsprüfung).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 3266-3274) - Begründung: Exakter Bedingungsausdruck im Code.
|
||||
Prüfidee: Rechnung mit global deaktiviertem, aber lokal aktiviertem ZUGFeRD → PDF enthält ZUGFeRD-Struktur (bestätigt ODER-Semantik der Aktivierungsquelle).
|
||||
Tracelinks: SyRS-014
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-016
|
||||
Titel: Verschlüsselung von Zertifikat und Passwörtern in PdfSigningBL
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente PdfSigningBL, AESCryptoLogic
|
||||
Vorbedingung: Ein Administrator speichert Signatureinstellungen (SavePdfSigningSettings).
|
||||
Fakt: Vor dem Schreiben werden Zertifikat (Base64) und Zertifikatspasswort separat über `_cryptoLogic.EncryptText(...)` verschlüsselt (Z. 86-90); beim Lesen (GetPdfSigningSettings, Z. 47-50) wird das TSA-Serverpasswort symmetrisch mit `_cryptoLogic.DecryptText` entschlüsselt, sofern nicht leer.
|
||||
Aussage: Die Komponente soll jedes sicherheitskritische Zugangsdatum (Zertifikat, Zertifikatspasswort, TSA-Passwort) vor der Persistierung mit AES verschlüsseln und beim Lesen transparent wieder entschlüsseln.
|
||||
Ergebnis: In der Datenbank liegt zu keinem Zeitpunkt ein Klartext-Passwort oder unverschlüsseltes Zertifikat für die PDF-Signatur vor.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs (Z. 29-90) - Begründung: Vollständige Lese-/Schreiblogik inkl. Ver-/Entschlüsselung.
|
||||
Prüfidee: Direktes Auslesen der zugrunde liegenden ApplicationSettings-Zeile für PdfSigningCertificatePassword zeigt keinen erkennbaren Klartextwert.
|
||||
Tracelinks: SyRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-017
|
||||
Titel: Blazor-Komponente WebReceiptOverview mit Token-Routing und Branding-Injection
|
||||
Ebene: SwRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Komponente CentronNexus (Blazor)
|
||||
Vorbedingung: Ein Browser ruft "/weboffer/{Token}" auf.
|
||||
Fakt: `@page "/weboffer/{Token}"` mit `@layout EmptyLayout`; Dependency Injection von ICentronService, IOptionsSnapshot<BrandingConfig>, IJSRuntime u. a.; bedingte Anzeige des Mandantenlogos nur wenn `Receipt?.MandatorImage` gesetzt UND nicht leer UND Base64-Konvertierung erfolgreich (`_mandantLogoAsBase64`).
|
||||
Aussage: Die Komponente soll den Token als alleinigen Routenparameter zur Beleg-Identifikation nutzen, ohne Authentifizierungs-Middleware zu durchlaufen, und die Darstellung durch injizierte, pro Mandant austauschbare Konfiguration (BrandingConfig) zu personalisieren.
|
||||
Ergebnis: Die Seite ist für jeden Inhaber eines gültigen Token-Links ohne weitere Anmeldeschritte erreichbar und zeigt mandantenspezifisches Branding.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor (Z. 1-90) - Begründung: Vollständige Routendefinition und Rendering-Logik.
|
||||
Prüfidee: Aufruf mit syntaktisch validem, aber nicht existierendem Token → definiertes Fehlverhalten (z. B. leere Seite/Fehlermeldung; exakter Mechanismus nicht verifiziert, siehe Hypothesen.md).
|
||||
Tracelinks: SyRS-016, SyRS-027
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-018
|
||||
Titel: Klasse DataSecurityBL: Statistikmethoden vollständig, Ausführungsmethode Stub
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Komponente DataSecurityBL
|
||||
Vorbedingung: Rechte- und Feature-Flag-Prüfung war erfolgreich.
|
||||
Fakt: GetDataSecurityCleanUpStats (Z. 34-62) implementiert vier vollständige Unterabfragen (GetCustomersWithLastActionOlderThan, GetDeletedCustomers, GetCrmActivitiesOlderThan, GetReceiptsOlderThan) mit konkreten SQL-Statements; DataSecurityExecuteCleanUp (Z. 64-70) besteht demgegenüber ausschließlich aus Rechteprüfung + `return Result.AsSuccess();` ohne jede Datenmanipulation.
|
||||
Aussage: Die Klasse DataSecurityBL soll sowohl die Analyse (Statistik) als auch die tatsächliche Ausführung der DSGVO-Datenbereinigung vollständig implementieren.
|
||||
Ergebnis: Aktuell: Statistikfunktion ist vollständig nutzbar, die eigentliche Bereinigungsausführung ist ein Platzhalter ohne Wirkung – ein Aufrufer, der Erfolg=Bereinigung durchgeführt interpretiert, wird fehlgeleitet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs (Z. 34-70, insbesondere 64-70) - Begründung: Direkter Vergleich beider Methodenkörper im selben Modul.
|
||||
Prüfidee: Aufruf von DataSecurityExecuteCleanUp mit denselben Filterkriterien wie eine zuvor als "zu bereinigen" ausgewiesene Statistik → betroffene Datensätze bleiben unverändert (Regressionstest zur Schließung dieser Lücke empfohlen).
|
||||
Tracelinks: SyRS-017, SyRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-019
|
||||
Titel: Entität HelpdeskStateBase als Stammdaten-Tabelle
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Entität HelpdeskStateBase
|
||||
Vorbedingung: Ein Ticket-Status soll definiert/verwendet werden.
|
||||
Fakt: Klasse mit exakt vier Feldern (Name, Number, Description, State als int?), kein Enum, keine feste Werteliste im Code.
|
||||
Aussage: Die Entität HelpdeskStateBase soll als frei erweiterbare Stammdatentabelle ohne Code-seitige Werteliste modelliert sein.
|
||||
Ergebnis: Neue Ticketstatus können ohne Codeänderung/Deployment angelegt werden, sofern eine entsprechende Verwaltungsoberfläche existiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskStateBase.cs (vollständige Datei) - Begründung: Vollständige, minimale Entitätsdefinition.
|
||||
Prüfidee: Datenbankseitiges Anlegen eines neuen HelpdeskStateBase-Datensatzes wird von der Anwendung ohne Codeänderung akzeptiert (keine Enum-Validierung im Entitätscode erkennbar).
|
||||
Tracelinks: SyRS-019
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-020
|
||||
Titel: Entität Helpdesk: Sperr-, Sichtbarkeits- und Hierarchiefelder
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Entität Helpdesk
|
||||
Vorbedingung: Ein Ticket wird angelegt oder bearbeitet.
|
||||
Fakt: Felder LockUserName (string)/LockUser (Employee) für pessimistische Sperre, IsOnlyInternalVisible (bool) für Sichtbarkeit, ParentHelpdeskI3D (int?) für Hierarchie, EscalationLevel (int), CreatedFromObjectI3D/CreatedFromObjectKind für Herkunftsverfolgung, IList<HelpdeskEditor> Editors für Mehrfachzuweisung.
|
||||
Aussage: Die Entität Helpdesk soll Bearbeitungssperre, interne Sichtbarkeit, Ticket-Hierarchie, Eskalationsstufe und Mehrfachbearbeiterzuweisung als reguläre, persistente Felder desselben Datensatzes abbilden.
|
||||
Ergebnis: Alle genannten Aspekte sind Teil eines einzigen konsistenten Datensatzes und können gemeinsam in einer Transaktion aktualisiert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs (Z. 49, 90-92, 95-98, 122, 126) - Begründung: Direkte Felddefinitionen.
|
||||
Prüfidee: Serialisierung/Deserialisierung eines Helpdesk-Datensatzes bewahrt alle genannten Feldwerte verlustfrei (Struktur-Test).
|
||||
Tracelinks: SyRS-020
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-021
|
||||
Titel: Methode UpdateBillingDateIsEnabled im TimerBillingSettingsPageViewModel
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Komponente TimerBillingSettingsPageViewModel (WPF)
|
||||
Vorbedingung: UseBillingDate oder ReceiptKind wurde durch den Benutzer geändert.
|
||||
Fakt: Methode liest CentronCache.Instance.ReceiptSettings.CanChangeDateInInvoices bzw. CanChangeDateInDeliveryLists abhängig von ReceiptKind, setzt BillingDateIsEnabled entsprechend, und formatiert bei Deaktivierung einen Hinweistext mit belegtypspezifischem Teilsatz ("der Rechnung" / "des Lieferscheins").
|
||||
Aussage: Die Methode soll bei jeder Änderung der auslösenden Properties (ReceiptKind, UseBillingDate) synchron die Enabled- und Hinweistext-Properties der UI aktualisieren, ohne dass eine explizite Aktion des Benutzers (z. B. Speichern) nötig ist.
|
||||
Ergebnis: Die UI reagiert unmittelbar und konsistent auf Property-Änderungen (reaktives Bindungsverhalten typisch für MVVM).
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, UpdateBillingDateIsEnabled (vollständiger Diff aus Commit baa9e7bd9b) - Begründung: Neu eingeführte, vollständige Methode.
|
||||
Prüfidee: Property-Change-Test: Setzen von ReceiptKind=InvoiceClass löst automatisch einen Aufruf von UpdateBillingDateIsEnabled aus (SetProperty-Callback, Z. 195-199 im Diff).
|
||||
Tracelinks: SyRS-021
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-022
|
||||
Titel: Methode UpdateArticlePurchasePriceThroughStockBooking (Haupt-/Nebenlager-Verzweigung)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente ArticleBL
|
||||
Vorbedingung: Eine Lagerbuchung mit Einkaufspreisbezug erfolgt (storage-Parameter bekannt).
|
||||
Fakt: Verzweigung anhand `storage.I3D <= 0` (Hauptlager) vs. sonst (Nebenlager, Z. 3607, 3653); im Hauptlager-Zweig wird zuerst RawEk2 aus dem aktuellen RawEk1-Wert der Datenbank gesetzt (Z. 3612-3620, LINQ-Update ohne vorheriges Laden der Entität), danach RawEk1/PurchasePrice bedingt auf Basis von `oldPurchasePrice != newPurchasePrice` unterschiedlich aktualisiert (Z. 3625-3651).
|
||||
Aussage: Die Methode soll die Preishistorisierung für Hauptlagerbuchungen als zweistufigen Set-basierten Datenbank-Update (nicht Entity-Load-and-Save) umsetzen und zwischen Buchungen mit und ohne tatsächliche Preisänderung unterscheiden.
|
||||
Ergebnis: RawEk2 enthält nach jeder Hauptlager-Buchung zuverlässig den unmittelbar vorherigen RawEk1-Wert, unabhängig davon, ob sich der Verkaufspreis (PurchasePrice) geändert hat.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs (Z. 3602-3652) - Begründung: Vollständige, gelesene Methode inkl. beider Verzweigungen.
|
||||
Prüfidee: Zwei Hauptlagerbuchungen mit identischem Preis → PurchasePrice bleibt unverändert, RawEk1/RawEk1Date werden dennoch aktualisiert (Else-Zweig Z. 3639-3651).
|
||||
Tracelinks: SyRS-022
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-023
|
||||
Titel: Klasse CentronHostedHandler (AuthorizationHandler<CentronHostedRequirement>)
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente ASP.NET-Core-Autorisierung
|
||||
Vorbedingung: Ein Endpunkt fordert die Policy "CentronHosted".
|
||||
Fakt: HandleRequirementAsync (Z. 12-24) ruft `LicenseManager.Instance.HasLicense(LicenseGuids.CentronInternal)` auf und ruft `context.Succeed(requirement)` nur im Erfolgsfall; kein expliziter Fail-Aufruf (Standardverhalten: Requirement bleibt unerfüllt, wenn Succeed nicht aufgerufen wird).
|
||||
Aussage: Die Handler-Klasse soll die Autorisierungsentscheidung ausschließlich an das Vorhandensein einer einzigen, fest kodierten Lizenz (CentronInternal) koppeln.
|
||||
Ergebnis: Endpunkte mit dieser Policy sind ausschließlich für Instanzen mit dieser spezifischen Lizenz erreichbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/CentronHostedAuthorization.cs (Z. 10-25) - Begründung: Vollständige Handler-Implementierung.
|
||||
Prüfidee: Unit-Test: HasLicense liefert false → context.HasSucceeded bleibt false nach Aufruf; HasLicense liefert true → context.HasSucceeded==true.
|
||||
Tracelinks: SyRS-023
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-024
|
||||
Titel: JWT-Bearer-Konfiguration mit vollständigen TokenValidationParameters
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente Centron.Host (Startup/DI)
|
||||
Vorbedingung: Der Host wird gestartet und die Authentifizierungspipeline konfiguriert.
|
||||
Fakt: `auth.AddJwtBearer(JwtBearerDefaults.AuthenticationScheme, "Bearer", options => {...})` setzt Authority und Audience aus jwtConfiguration sowie alle sieben TokenValidationParameters-Flags auf true (Z. 188-203); zusätzlich `JwtSecurityTokenHandler.DefaultMapInboundClaims = false` (Z. 185) verhindert automatisches Claim-Remapping.
|
||||
Aussage: Die Konfiguration soll den JWT-Bearer-Handler mit der maximal strengen Kombination der Standard-Validierungsoptionen registrieren und das automatische Claim-Mapping deaktivieren, um Claim-Namen unverändert (wie im Token ausgestellt) verfügbar zu machen.
|
||||
Ergebnis: Nur strukturell und kryptographisch vollständig valide, nicht abgelaufene, nicht wiederholte Tokens der richtigen Authority/Audience werden akzeptiert; Claims sind im Code unter ihrem Original-Namen verfügbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs (Z. 184-205) - Begründung: Vollständiger Konfigurationsblock.
|
||||
Prüfidee: Token mit falscher Audience → Ablehnung (ValidateAudience); Token mit Claim "sub", DefaultMapInboundClaims=false → Claim bleibt "sub", nicht auf ClaimTypes.NameIdentifier gemappt.
|
||||
Tracelinks: SyRS-024
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-025
|
||||
Titel: Registrierung AddCentronTicket() und Policy "SecretKey" mit SecretKeyRequirement
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Komponente Centron.Host, SecretKeyHandler
|
||||
Vorbedingung: Startup-Konfiguration der Authentifizierung.
|
||||
Fakt: `f.AddAuthentication(TicketAuthenticationDefaults.AuthenticationScheme); auth.AddCentronTicket();` registriert das Ticket-Schema als Default; separat registriert `f.AddAuthorization(options => options.AddPolicy("SecretKey", policy => policy.Requirements.Add(new SecretKeyRequirement(nexusConnectionKey))))` eine eigenständige Policy mit `f.AddSingleton<IAuthorizationHandler, SecretKeyHandler>()`.
|
||||
Aussage: Die Komponente soll das Ticket-Schema als Standard-Authentifizierung setzen und zusätzlich eine unabhängige, mit einem konfigurierten Schlüssel (nexusConnectionKey) parametrisierte Policy für die Nexus-Anbindung bereitstellen.
|
||||
Ergebnis: Endpunkte können wahlweise Ticket-, JWT- oder SecretKey-basierte Autorisierung verlangen, jeweils über eigene, unabhängig konfigurierbare Mechanismen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs (Z. 186-187, 207-213, 216) - Begründung: Vollständige Registrierungsblöcke.
|
||||
- [KONTEXT] src/webservice/Centron.Host/RealTimeServices/SecretKeyHandler.cs (Dateiname referenziert, Inhalt nicht gelesen) - Begründung: Bestätigt Existenz der Handler-Implementierung, Details nicht verifiziert.
|
||||
Prüfidee: Request mit korrektem SecretKey, aber ohne JWT/Ticket → Zugriff auf SecretKey-Policy-geschützte Endpunkte erfolgreich, auf JWT-geschützte Endpunkte weiterhin verweigert.
|
||||
Tracelinks: SyRS-025
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-026
|
||||
Titel: Architekturmuster BaseBL/DAOSession als Basis aller Fachlogikklassen
|
||||
Ebene: SwRS
|
||||
Typ: Wartbarkeit
|
||||
Akteur: Komponente Centron.BL (durchgängig)
|
||||
Vorbedingung: Eine neue Fachlogikklasse wird implementiert.
|
||||
Fakt: Alle in dieser Analyse gelesenen BL-Klassen (AppRightsBL, ReceiptBL, NumberGroupBL, DataSecurityBL, PdfSigningBL, ArticleBL, TimingSettingsBL) erben von BaseBL und erhalten eine DAOSession per Konstruktorinjektion; Datenzugriff erfolgt einheitlich über `Session.GetGenericDAO<T>()`, `Session.GetSession().Query<T>()` oder `Session.Advanced.RawSqlAccess`.
|
||||
Aussage: Jede Fachlogikklasse im Backend soll dem einheitlichen Muster BaseBL + DAOSession-Injektion folgen, statt eigene Datenzugriffsmechanismen zu implementieren.
|
||||
Ergebnis: Datenzugriff, Transaktionshandling (Session.WithTransaction) und Caching (Session.Advanced.Cache) stehen jeder Fachlogikklasse einheitlich zur Verfügung.
|
||||
Belege:
|
||||
- [PRIMÄR] Konstruktorsignaturen in allen genannten Klassen, z. B. AppRightsBL.cs (Z. 29), NumberGroupBL.cs (Z. 18) - Begründung: Identisches Muster in unabhängigen, an verschiedenen Stellen der Codebasis liegenden Klassen.
|
||||
Prüfidee: Stichprobenartige Codeanalyse über weitere *BL-Klassen außerhalb der explizit gelesenen Stichprobe bestätigt dasselbe Muster (Konsistenzprüfung, im Rahmen dieser Iteration nicht flächendeckend durchgeführt).
|
||||
Tracelinks: SyRS-033
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-027
|
||||
Titel: Rückgabetyp Result/Result\<T\> mit MessageCode-Enum
|
||||
Ebene: SwRS
|
||||
Typ: Wartbarkeit
|
||||
Akteur: Komponente Centron.Interfaces (Result, DefaultMessageCodes)
|
||||
Vorbedingung: Eine Fachmethode kann fehlschlagen.
|
||||
Fakt: Durchgängig verwendete Muster `Result.AsSuccess()/Result.AsError(message, messageCode)` bzw. generisch `Result<T>.AsSuccess(data)/Result<T>.AsError(...)`; beobachtete konkrete MessageCodes: RightCheckFailed, ChangedByOtherInstance, BadRequest, ErrorMessage.
|
||||
Aussage: Die Typen Result/Result\<T\> sollen als einheitlicher, in der gesamten Backend-Fachlogik verwendeter Rückgabekanal für Erfolg/Fehler mit optionalem maschinenlesbaren MessageCode dienen.
|
||||
Ergebnis: Aufrufende Schichten können anhand von `result.Status` und `result.MessageCode` generisch reagieren (z. B. HTTP-Statuscode-Mapping im Controller), ohne belegartspezifische Sonderbehandlung je Methode.
|
||||
Belege:
|
||||
- [PRIMÄR] Durchgängige Verwendung in AppRightsBL.cs, ReceiptBL.cs, DataSecurityBL.cs, PdfSigningBL.cs (siehe jeweilige Zeilenangaben in StRS/SyRS) - Begründung: Konsistentes Muster über mehrere unabhängige Module.
|
||||
- [SEKUNDÄR] src/backend/Centron.Interfaces/Results/DefaultMessageCodes.cs (referenziert) - Begründung: Zentrale Enum-Definition, nicht vollständig gelesen.
|
||||
Prüfidee: Codeanalyse: Anteil öffentlicher BL-Methoden mit Rückgabetyp Result/Result\<T\> in den analysierten Klassen (Stichprobe: deutlich überwiegend, exakte Quote nicht vollständig erhoben).
|
||||
Tracelinks: SyRS-033
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-028
|
||||
Titel: Enum CentronObjectKindNumeric mit Erweiterungsregel "nur anhängen"
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Komponente Centron.Interfaces
|
||||
Vorbedingung: Eine neue Objektart wird im Gesamtsystem eingeführt.
|
||||
Fakt: Kommentarblock (Z. 6-14) verlangt ausdrücklich, neue Werte ausschließlich ans Ende der Enum-Definition anzuhängen ("New types MUST be inserted at the end"), da sonst der Web-Service brechen würde; neue .NET-Werte beginnen ab 7600000, um Kollisionen mit dem parallel aktiven Delphi-System zu vermeiden.
|
||||
Aussage: Die Enum CentronObjectKindNumeric soll ausschließlich additiv erweitert werden; bestehende numerische Werte dürfen nicht verändert oder wiederverwendet werden.
|
||||
Ergebnis: Web-Service-Konsumenten, die auf den numerischen Werten basieren, bleiben über Versionsgrenzen hinweg kompatibel.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (Z. 6-14, 263 Kommentar "Nächste .NET Konstante: 7600154") - Begründung: Expliziter Wartungs-Kommentar mit Begründung und laufender Pflege des nächsten freien Werts.
|
||||
Prüfidee: Historische Konsistenzprüfung: keine doppelt vergebenen numerischen Werte in der Enum-Definition (Stichprobenprüfung während der Analyse ergab keine Duplikate, siehe Analysebericht Konsistenzcheck).
|
||||
Tracelinks: SyRS-007, SyRS-034
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+624
@@ -0,0 +1,624 @@
|
||||
# System Requirements Specification (SyRS)
|
||||
|
||||
Ebene: Systemverhalten, Schnittstellen, Performance- und Sicherheitsanforderungen. Nicht-funktionale Anforderungen sind zusätzlich einem Qualitätsmerkmal nach ISO/IEC 25010 zugeordnet (Feld `Typ` bzw. Klammerzusatz im Titel).
|
||||
|
||||
```
|
||||
ID: SyRS-001
|
||||
Titel: Gruppenbasiertes Rechtemodell mit zentraler Prüffunktion
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (AppRightsBL)
|
||||
Vorbedingung: Ein Recht (AppRight) ist mindestens einer Gruppe (AppGroup) zugeordnet, der der anfragende Benutzer angehört.
|
||||
Fakt: HasUserRight(appUserI3D, rightID) lädt (gecacht) alle Recht-IDs eines Benutzers per SQL-JOIN über Sichtrus/Sichmemb und prüft Enthaltensein; GetRightsFromCurrentUser aggregiert Rechte aus allen Gruppen eines Benutzers.
|
||||
Aussage: Das System soll eine zentrale, wiederverwendbare Funktion bereitstellen, die für einen gegebenen Benutzer und ein gegebenes Recht eindeutig bestimmt, ob der Benutzer über seine Gruppenzugehörigkeiten berechtigt ist.
|
||||
Ergebnis: HasUserRight liefert für jede Kombination aus Benutzer und Recht ein deterministisches Boolean-Ergebnis.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, HasUserRight (Z. 644-649), GetAllAppRightsFromUser (Z. 651-664) - Begründung: Direkte, aktiv genutzte Implementierung.
|
||||
Prüfidee: Unit-/Integrationstest: Benutzer mit Gruppenmitgliedschaft X, Gruppe X besitzt Recht Y → HasUserRight(User, Y)==true; Entzug des Rechts → false nach Cache-Invalidierung.
|
||||
Tracelinks: StRS-001; SwRS-001, SwRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-002
|
||||
Titel: Deklarative Rechteprüfung auf API-Ebene (Authorization-Filter)
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ASP.NET-Core-Pipeline)
|
||||
Vorbedingung: Ein API-Controller/eine Action ist mit [AuthorizeUserRight]/[AuthorizeAnyUserRight]/[AuthorizeAllUserRights] annotiert.
|
||||
Fakt: UserRightAuthorizationFilter.OnAuthorization prüft vor Ausführung der Action, ob ein Benutzer authentifiziert ist (sonst 401) und ob HasUserRight() für die angegebene(n) Recht-ID(s) erfüllt ist (sonst 403).
|
||||
Aussage: Das System soll Rechteprüfungen für REST-API-Endpunkte deklarativ als Authorization-Filter vor der eigentlichen Action ausführen und bei fehlender Authentifizierung mit 401, bei fehlendem Recht mit 403 antworten.
|
||||
Ergebnis: Kein Action-Code wird ausgeführt, wenn Authentifizierung oder Recht fehlen; HTTP-Statuscodes sind für Client-Fehlerbehandlung eindeutig unterscheidbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs (Z. 17-56) - Begründung: Aktive Filterimplementierung in der ASP.NET-Core-Pipeline.
|
||||
- [SEKUNDÄR] src/webservice/Centron.Controllers/Authorization/README.md (Z. 85-91) - Begründung: Dokumentiert erwartetes HTTP-Statuscode-Verhalten.
|
||||
Prüfidee: Integrationstest: Aufruf eines annotierten Endpunkts ohne Login → 401; mit Login aber ohne Recht → 403; mit Recht → 200.
|
||||
Tracelinks: StRS-001; SwRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-003
|
||||
Titel: Vollständiger Ausschluss von WebAccounts von interner Belegeinsicht
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein LoggedInUser mit IsWebAccountLogin=true ruft eine Belegeinsichtsfunktion auf.
|
||||
Fakt: CanUserViewReceipt gibt unmittelbar (vor jeder weiteren Prüfung) einen Fehler mit MessageCode RightCheckFailed zurück, wenn loggedInUser.IsWebAccountLogin wahr ist.
|
||||
Aussage: Das System soll für WebAccount-Logins jede Prüfung interner Belegrechte durch eine vorgelagerte, unbedingte Sperre ersetzen.
|
||||
Ergebnis: Es ist architektonisch ausgeschlossen, dass ein WebAccount über die interne Belegprüfung Zugriff erhält, unabhängig von eventuell vorhandenen AppRight-Datensätzen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, CanUserViewReceipt (Z. 10297-10311) - Begründung: Bedingung wird als erste Prüfung ausgewertet (fail-fast).
|
||||
Prüfidee: WebAccount-Login mit (fehlerhaft) hinterlegtem internen AppRight versucht Belegeinsicht → dennoch RightCheckFailed.
|
||||
Tracelinks: StRS-002; SwRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-004
|
||||
Titel: Zweistufige Rechteprüfung: allgemeines Recht + Filialabgleich
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ReceiptBL, AppRightsBL)
|
||||
Vorbedingung: Ein Recht existiert in einer branch-eingeschränkten Variante.
|
||||
Fakt: CanUserEditReceipt prüft zunächst das allgemeine belegartspezifische Bearbeitungsrecht (HasRightToEditReceipt), danach separat, ob nur die eigene Filiale erlaubt ist (HasRightToEditReceiptOnlyOwnBranch) und vergleicht in diesem Fall BranchBL.IsBranchEqual(appUser.Employee.BranchI3D, receiptBranchI3D).
|
||||
Aussage: Das System soll Filialbeschränkungen als zusätzliche, nach der allgemeinen Rechteprüfung ausgeführte Bedingung behandeln, sodass beide Prüfungen unabhängig voneinander fehlschlagen können und jeweils eine spezifische Fehlermeldung liefern.
|
||||
Ergebnis: Fehlermeldungen unterscheiden klar zwischen "kein Recht am Belegtyp" und "Recht vorhanden, aber falsche Filiale".
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, CanUserEditReceipt (Z. 10272-10295) - Begründung: Zwei sequenzielle, unabhängige Prüfblöcke mit je eigener Fehlermeldung.
|
||||
Prüfidee: Benutzer ohne jegliches Bearbeitungsrecht → Meldung "nicht das Recht ... zu bearbeiten"; Benutzer mit Recht, aber falscher Filiale → Meldung "... einer anderen Filiale zu bearbeiten".
|
||||
Tracelinks: StRS-003; SwRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-005
|
||||
Titel: Geschützte Administratorengruppe mit eingeschränkter Änderungsmenge
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (AppRightsBL)
|
||||
Vorbedingung: Eine Änderung an der Gruppe I3D=6 bzw. Name "Administratoren" wird angefordert.
|
||||
Fakt: DeleteRightGroup lehnt die Löschung dieser Gruppe unabhängig vom aufrufenden Benutzer ab; SaveAndAssignGroupToRight/RemoveAssignGroupToRight prüfen bei dieser Gruppe zusätzlich, ob das betroffene Recht in der Whitelist GetAssignableAdminRightI3Ds (38 fest kodierte Recht-IDs) enthalten ist.
|
||||
Aussage: Das System soll strukturelle Änderungen an der Administratorengruppe (Löschung uneingeschränkt, Rechteänderung nur innerhalb einer festen Whitelist) unabhängig von Benutzerrechten unterbinden.
|
||||
Ergebnis: Die Administratorengruppe kann nicht gelöscht und nicht außerhalb der Whitelist in ihren Rechten reduziert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 261-299, 348-374, 714-759) - Begründung: Drei zusammenhängende Schutzmechanismen im selben Modul.
|
||||
Prüfidee: Versuch, ein nicht in der Whitelist enthaltenes Recht (z. B. Rechteverwaltung selbst) von der Administratorengruppe zu entziehen → RemoveAssignGroupToRight liefert false.
|
||||
Tracelinks: StRS-004; SwRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-006
|
||||
Titel: Revisionssichere Protokollierung von Rechteänderungen
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit (Nachvollziehbarkeit, ISO 25010: Sicherheit/Accountability)
|
||||
Akteur: System (AppRightsBL)
|
||||
Vorbedingung: Eine Rechte-, Gruppen- oder Mitgliedschaftsänderung wird ausgeführt.
|
||||
Fakt: Jede der Methoden AddRightToRightGroup, RemoveRightFromRightGroup, AddUserToRightGroup, RemoveUserFromRightGroup, DeleteRightGroup, SaveRightGroup(neu), CopyRightGroup ruft eine spezialisierte Write*Log-Methode auf, die einen AppRightLog-Datensatz mit Kind, Objektbezeichnung, Klartextbeschreibung, ausführendem Benutzer (Employee.I3D) und Zeitstempel persistiert.
|
||||
Aussage: Das System soll jede sicherheitsrelevante Änderung an Rechten und Gruppen als unveränderlichen Log-Eintrag mit Benutzer- und Zeitbezug persistieren.
|
||||
Ergebnis: GetAllAppRightLogs liefert eine vollständige, chronologisch sortierte Historie aller Rechteänderungen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Region "Logging" (Z. 761-858) - Begründung: Konsistentes Muster über alle änderungsrelevanten Methoden hinweg.
|
||||
Prüfidee: Nach AddRightToRightGroup existiert genau ein neuer AppRightLog-Eintrag mit Kind=AddRightToGroup und korrektem Beschreibungstext.
|
||||
Tracelinks: StRS-005; SwRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-007
|
||||
Titel: Einheitliches Belegdatenmodell über alle Belegarten
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: Eine konkrete Belegart (Angebot, Auftrag, ...) wird instanziiert.
|
||||
Fakt: ReceiptBase definiert als abstrakte Basisklasse gemeinsame Felder (Number, Date, Version, State, BranchI3D, Currency*, Adressfelder, Created/Changed-Metadaten, ConcurrencyControlGuid) sowie abstrakte Positions-Operationen (GetReceiptItems, AddItem, RemoveItem), die jede konkrete Belegart implementieren muss.
|
||||
Aussage: Das System soll alle Belegarten über eine gemeinsame Basisklasse mit einheitlichem Kern-Datenmodell und einheitlichem Positions-Zugriffsvertrag abbilden.
|
||||
Ergebnis: Generische Belegoperationen (Statusprüfung, Nummernvergabe, Concurrency-Check) können unabhängig von der konkreten Belegart implementiert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs (vollständige Datei) - Begründung: Definiert exakt dieses Modell.
|
||||
Prüfidee: Für jede Unterklasse von ReceiptBase existieren gültige Implementierungen der vier abstrakten Members (Compile-Time-Prüfung).
|
||||
Tracelinks: StRS-006; SwRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-008
|
||||
Titel: Nachverfolgung übernommener Belegpositionen (Forwarding)
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein Beleg oder einzelne seiner Positionen wurden in einen Folgebeleg übernommen.
|
||||
Fakt: GetReceiptForwardedInto ermittelt zu einem Beleg alle Folgebelege, die referenzierte Positions-I3Ds enthalten, wobei nur Folgebelege mit OtherReceiptState != Canceled berücksichtigt werden (Z. 9942-9946).
|
||||
Aussage: Das System soll zu jedem Beleg abrufbar machen, in welche nicht-stornierten Folgebelege seine Positionen übernommen wurden.
|
||||
Ergebnis: Löschungen/Entfernungen von Positionen können gegen bereits weitergeführte (nicht stornierte) Verwendungen geprüft werden (Schutz vor Inkonsistenz in der Belegkette).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 9938-9946) - Begründung: Konkrete Verwendung zur Verhinderung des Entfernens bereits weitergeführter Positionen.
|
||||
Prüfidee: Position P eines Angebots wurde in einen aktiven Auftrag übernommen → Versuch, P aus dem Angebot zu entfernen, wird als "removedPositionsThatCouldNotBeRemoved" erkannt.
|
||||
Tracelinks: StRS-006; SwRS-009
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-009
|
||||
Titel: Statusabhängige Sperre von Zahlungsänderungen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein Beleg befindet sich im Status Canceled.
|
||||
Fakt: UpdateReceiptIsPaid prüft receipt.State == ReceiptState.Canceled und liefert in diesem Fall unabhängig von Rechten einen Fachfehler ("...wurde stoniert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden.").
|
||||
Aussage: Das System soll Statusänderungen am Zahlungsstatus eines stornierten Belegs grundsätzlich unterbinden.
|
||||
Ergebnis: Stornierte Belege können nicht nachträglich als bezahlt/unbezahlt markiert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 4936-4937) - Begründung: Explizite, unbedingte Statusprüfung mit Fachfehler.
|
||||
Prüfidee: UpdateReceiptIsPaid auf einem Canceled-Beleg → Result.AsError, kein Datenbank-Write.
|
||||
Tracelinks: StRS-007; SwRS-010
|
||||
Konsolidierung: Kandidat: SyRS-013 (beide betreffen UpdateReceiptIsPaid, unterschiedliche Prüfaspekte derselben Methode – im Zielsystem ggf. als eine zusammengesetzte Regel modellieren)
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-010
|
||||
Titel: Kollisionsgeprüfte, atomare Nummernvergabe je Nummernkreis
|
||||
Ebene: SyRS
|
||||
Typ: Daten (Zuverlässigkeit, ISO 25010: Reliability)
|
||||
Akteur: System (NumberGroupBL)
|
||||
Vorbedingung: Ein Nummernkreis-Objekt (NumberGroup) existiert für die gewünschte Kombination aus Mandant/Filiale/Belegart.
|
||||
Fakt: FindNextNumber addiert das konfigurierte Intervall auf den aktuellen Zähler und erhöht iterativ weiter, solange die resultierende Nummer bereits in der Zieltabelle (bzw. zusätzlich in Kunden/Kreditor bei den Sonderfällen Customer/Supplier) existiert; GetNextNumber persistiert die neue Nummer nur über ein bedingtes UPDATE (WHERE Current=alterWert) und wiederholt den gesamten Vorgang bei Nichttreffer (rowCountChanged!=1).
|
||||
Aussage: Das System soll die Vergabe einer neuen Belegnummer als atomare, gegen Parallelzugriff abgesicherte Operation ausführen, die niemals eine bereits verwendete Nummer zurückgibt.
|
||||
Ergebnis: Unter Lastbedingungen mit mehreren gleichzeitigen Speichervorgängen werden keine doppelten Nummern innerhalb desselben Nummernkreises vergeben.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs, GetNextNumber (Z. 62-92), FindNextNumber (Z. 94-134) - Begründung: Vollständiger, aktiv genutzter Algorithmus inkl. Retry-Schleife.
|
||||
Prüfidee: Lasttest: N parallele Aufrufe von GetNextNumber(..., updateDatabase:true) auf demselben Nummernkreis liefern N paarweise verschiedene Nummern.
|
||||
Tracelinks: StRS-008; SwRS-011, SwRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-011
|
||||
Titel: Mandanten-/filialspezifische Nummernkreis-Trennung
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (NumberGroupBL, MandatoryBL)
|
||||
Vorbedingung: Mehrere Mandanten bzw. Filialen sind im System angelegt.
|
||||
Fakt: CreateNumberGroups erzeugt je Belegart getrennte NumberGroup-Objekte pro MandantI3D und optional BranchI3D; ReceiptBL.UpdateReceiptNumber wählt zusätzlich einen separaten Nummernkreis für Belegvorlagen (anhand einer konfigurierten "Vorlagen-Kundennummer").
|
||||
Aussage: Das System soll für jeden Mandanten und optional jede Filiale unabhängige Nummernkreise je Belegart führen, sowie Belegvorlagen aus einem eigenen, von realen Belegen getrennten Nummernkreis versorgen.
|
||||
Ergebnis: Belegnummern verschiedener Mandanten/Filialen können sich überschneiden, ohne dass dies zu Konflikten führt, da sie fachlich getrennten Nummernkreisen entstammen; Vorlagen erzeugen keine "echten" fortlaufenden Nummern.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Company/NumberGroupBL.cs, CreateNumberGroups (Z. 154-187) - Begründung: Aktive Erzeugungslogik mit Mandant-/Filial-Schlüsseln.
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, UpdateReceiptNumber (Z. 7265-7285) - Begründung: Sonderfallbehandlung für Belegvorlagen.
|
||||
Prüfidee: Zwei Filialen desselben Mandanten erzeugen unabhängig voneinander Rechnung Nr. 1000 ohne Kollision (unterschiedliche NumberGroup-Objekte).
|
||||
Tracelinks: StRS-008; SwRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-012
|
||||
Titel: Optimistische Sperrung über Concurrency-GUID und Versionsfolge
|
||||
Ebene: SyRS
|
||||
Typ: Daten (Zuverlässigkeit)
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein Beleg mit vorhandener ConcurrencyControlGuid/Version wird erneut gespeichert.
|
||||
Fakt: Mehrere Schreibpfade vergleichen die übergebene ConcurrencyControlGuid mit dem persistierten Wert (z. B. Z. 4884-4885, 4939-4940) und lehnen bei Abweichung mit MessageCode ChangedByOtherInstance ab; SaveReceipt validiert zusätzlich, dass die Versionsnummer entweder die erste Version ist oder exakt der Vorgängerversion+1 entspricht (Z. 3568-3578).
|
||||
Aussage: Das System soll konkurrierende Schreibzugriffe auf denselben Beleg über eine Kombination aus optimistischem GUID-Vergleich und strikter Versionsfolgeprüfung erkennen und ablehnen.
|
||||
Ergebnis: Ein Schreibversuch auf Basis eines veralteten Belegstands wird zuverlässig zurückgewiesen, bevor Daten überschrieben werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 3568-3578, 4884-4885, 4939-4940) - Begründung: Zwei unabhängige, jeweils aktiv durchgesetzte Prüfmechanismen.
|
||||
Prüfidee: Speichern mit veralteter ConcurrencyControlGuid → Fehler ChangedByOtherInstance; Speichern mit übersprungener Versionsnummer (z. B. v1→v3) → Fehler "keine gültige Versionsnummer".
|
||||
Tracelinks: StRS-009; SwRS-014
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-013
|
||||
Titel: Alternative Berechtigung für Zahlungseingangserfassung
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ReceiptBL), Buchhaltung/Controlling
|
||||
Vorbedingung: Ein Benutzer ohne allgemeines Bearbeitungsrecht am Belegtyp versucht, den Zahlungsstatus zu ändern.
|
||||
Fakt: UpdateReceiptIsPaid fängt den Fehlerfall RightCheckFailed aus CanUserEditReceipt gezielt ab und prüft alternativ HasUserRight(..., INCOMING_PAYMENT_TRANSACTIONS); nur wenn auch dieses Recht fehlt, wird der Zugriff endgültig verweigert.
|
||||
Aussage: Das System soll für die Erfassung von Zahlungseingängen eine vom allgemeinen Belegbearbeitungsrecht unabhängige Sonderberechtigung als gleichwertige Alternative zulassen.
|
||||
Ergebnis: Buchhaltungsmitarbeiter ohne Verkaufsrechte können dennoch Zahlungseingänge erfassen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 4920-4934) - Begründung: Explizite Sonderfallbehandlung mit Kommentar "special case".
|
||||
Prüfidee: Benutzer mit ausschließlich INCOMING_PAYMENT_TRANSACTIONS-Recht kann UpdateReceiptIsPaid erfolgreich ausführen, obwohl CanUserEditReceipt für ihn fehlschlägt.
|
||||
Tracelinks: StRS-010; SwRS-010
|
||||
Konsolidierung: Kandidat: SyRS-009 (siehe dort)
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-014
|
||||
Titel: Bedingte Erzeugung ZUGFeRD-konformer E-Rechnungen
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (ReceiptBL, InvoiceZugferdBL)
|
||||
Vorbedingung: Der zu druckende/exportierende Beleg ist vom Typ InvoiceClass oder CreditVoucherClass.
|
||||
Fakt: Vor Erzeugung des Belegreports wird geprüft: Belegart ist Rechnung/Gutschrift UND (globale ZUGFeRD-Einstellung ODER lokale Beleg-Einstellung) aktiv UND Beleg ist nicht storniert; nur dann wird der PDF-Ausgabepuffer um die ZUGFeRD-Struktur ergänzt.
|
||||
Aussage: Das System soll die Erzeugung ZUGFeRD-konformer E-Rechnungen an drei kombinierte Bedingungen (Belegart, Aktivierung, Nicht-Storniert) knüpfen.
|
||||
Ergebnis: Nur tatsächlich gültige Rechnungen/Gutschriften bei aktivierter Einstellung erhalten eine eingebettete ZUGFeRD-Struktur; stornierte Belege werden ausgeschlossen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 3266-3274) - Begründung: Zusammengesetzte Bedingung mit allen drei Kriterien im Code sichtbar.
|
||||
Prüfidee: Stornierte Rechnung mit aktivierter ZUGFeRD-Einstellung wird gedruckt → resultierendes PDF enthält KEINE ZUGFeRD-Struktur.
|
||||
Tracelinks: StRS-011; SwRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-015
|
||||
Titel: Verschlüsselte Speicherung von Signatur-Zugangsdaten
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (PdfSigningBL)
|
||||
Vorbedingung: Ein Administrator hinterlegt Zertifikat, Zertifikatspasswort oder TSA-Zugangsdaten.
|
||||
Fakt: SavePdfSigningSettings verlangt das Recht Administration.SETTINGS; Zertifikat und Passwörter werden vor der Persistierung über AESCryptoLogic.EncryptText verschlüsselt (Z. 86-90) bzw. beim Lesen entschlüsselt (Z. 47-50).
|
||||
Aussage: Das System soll sicherheitskritische Zugangsdaten für die digitale Signatur (Zertifikat, Passwörter) ausschließlich verschlüsselt speichern und deren Änderung auf Benutzer mit Administrationsrecht beschränken.
|
||||
Ergebnis: Ein direkter Datenbankzugriff auf die ApplicationSettings-Tabelle liefert keine Klartext-Zugangsdaten für die Signaturfunktion.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs (Z. 29-90) - Begründung: Symmetrisches Verschlüsseln/Entschlüsseln sowie Rechteprüfung im selben Modul.
|
||||
Prüfidee: Auslesen der zugrunde liegenden ApplicationSettings-Datensätze außerhalb der BL zeigt Base64/verschlüsselten, nicht lesbaren Wert für Zertifikat und Passwort.
|
||||
Tracelinks: StRS-012; SwRS-016
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-016
|
||||
Titel: Tokenbasierter, login-freier Zugriff auf Web-Angebote
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (CentronNexus), anonymer Angebotsempfänger
|
||||
Vorbedingung: Ein Angebot wurde für die Web-Freigabe vorbereitet und ein Token generiert.
|
||||
Fakt: Die Blazor-Route "/weboffer/{Token}" bindet ein EmptyLayout (kein globales Login-Menü/keine Session-Pflicht) und lädt den Beleg über den Token-Parameter statt über eine Benutzer-/Session-Identität.
|
||||
Aussage: Das System soll den Abruf eines freigegebenen Angebots über einen in der URL enthaltenen Token ermöglichen, ohne dass der Empfänger sich zuvor authentifizieren muss.
|
||||
Ergebnis: Der Token allein ist hinreichend und notwendig, um das zugehörige Angebot abzurufen; es ist kein WebAccount erforderlich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor (Z. 1-3) - Begründung: Routendefinition und Layout-Wahl direkt im UI-Code.
|
||||
Prüfidee: Aufruf der Route mit gültigem Token in einem Browser ohne bestehende Session zeigt den Beleg an.
|
||||
Tracelinks: StRS-013; SwRS-017
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-017
|
||||
Titel: Rechte- und lizenzabhängige Freischaltung der DSGVO-Bereinigungsfunktion
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (DataSecurityBL), Datenschutzbeauftragter
|
||||
Vorbedingung: Ein Benutzer ruft die DSGVO-Bereinigungsstatistik oder -Ausführung auf.
|
||||
Fakt: Sowohl GetDataSecurityCleanUpStats als auch DataSecurityExecuteCleanUp prüfen identisch: currentUser.HasUserRight(ACCESS_CLEANUP_DATABASE) UND ModuleFeatures.IsDsgvoDatabaseCleanupAvailable (Feature-/Lizenzschalter).
|
||||
Aussage: Das System soll den Zugriff auf DSGVO-Bereinigungsfunktionen sowohl an ein Benutzerrecht als auch an eine global aktivierbare Modul-/Lizenzeinstellung koppeln.
|
||||
Ergebnis: Ohne beide Bedingungen ist weder die Statistikabfrage noch der (im aktuellen Code wirkungslose) Ausführungsaufruf möglich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs (Z. 36, 66) - Begründung: Identische zusammengesetzte Bedingung an beiden Eintrittspunkten.
|
||||
Prüfidee: Benutzer mit Recht, aber deaktiviertem Feature-Flag → "Insufficient rights!"; Benutzer ohne Recht, aber aktiviertem Flag → ebenfalls "Insufficient rights!".
|
||||
Tracelinks: StRS-014; SwRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-018
|
||||
Titel: Unvollständige Implementierung der automatisierten DSGVO-Datenbereinigung
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (DataSecurityBL)
|
||||
Vorbedingung: Ein berechtigter Benutzer ruft DataSecurityExecuteCleanUp mit ausgewählten Bereinigungsarten auf.
|
||||
Fakt: Die Methode (Z. 64-70) enthält nach der Rechteprüfung ausschließlich `return Result.AsSuccess();` ohne jegliche Lösch-, Anonymisierungs- oder sonstige Datenbankänderung.
|
||||
Aussage: Das System soll die tatsächliche Datenbereinigung entsprechend der zuvor angezeigten Statistiken durchführen. [HYPOTHESE: im untersuchten Codestand nicht erfüllt]
|
||||
Ergebnis: Aktuell: Der Aufruf meldet Erfolg zurück, ohne dass Daten verändert werden – eine funktionale Lücke zwischen UI-Erwartung (Bereinigung wurde durchgeführt) und tatsächlichem Verhalten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/DataSecurity/DataSecurityBL.cs, DataSecurityExecuteCleanUp (Z. 64-70) - Begründung: Vollständiger Methodenkörper zeigt fehlende Umsetzung.
|
||||
Prüfidee: Vergleich des Datenbankinhalts (betroffene Tabellen) vor und nach Aufruf von DataSecurityExecuteCleanUp mit denselben Filterkriterien wie zuvor in GetDataSecurityCleanUpStats verwendet → keine Änderung erwartet (bestätigt Lücke).
|
||||
Tracelinks: StRS-014; SwRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-019
|
||||
Titel: Konfigurierbares, stammdatenbasiertes Ticket-Statusmodell
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System, Systemadministrator
|
||||
Vorbedingung: Ein Mandant möchte eigene Ticket-Statuswerte definieren.
|
||||
Fakt: HelpdeskStateBase ist eine reguläre, per Stammdaten pflegbare Entität (Name, Number, Description, State-Flag) und kein Code-Enum wie ReceiptState.
|
||||
Aussage: Das System soll das Ticket-Statusmodell im Gegensatz zum Belegstatus als frei konfigurierbare Stammdaten führen, um mandantenspezifische Ticket-Workflows zu ermöglichen.
|
||||
Ergebnis: Administratoren können eigene Ticketstatus mit eigener Bezeichnung anlegen, ohne dass eine Code-Änderung nötig ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskStateBase.cs - Begründung: Datenmodell ohne Enum-Bindung.
|
||||
Prüfidee: Anlage eines neuen HelpdeskStateBase-Datensatzes über die Stammdatenverwaltung; neuer Status steht danach für Tickets zur Auswahl (Detailmechanismus der UI-Anbindung nicht vollständig verifiziert).
|
||||
Tracelinks: StRS-015; SwRS-019
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-020
|
||||
Titel: Pessimistische Bearbeitungssperre und Sichtbarkeitssteuerung bei Tickets
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System, Helpdesk-/Servicemitarbeiter
|
||||
Vorbedingung: Ein Ticket wird von einem Mitarbeiter zur Bearbeitung geöffnet.
|
||||
Fakt: Helpdesk trägt LockUserName/LockUser-Felder (pessimistische Sperre) sowie IsOnlyInternalVisible zur Steuerung, ob ein Inhalt für Kunden sichtbar ist, zusätzlich ParentHelpdeskI3D für Ticket-Hierarchien und EscalationLevel für Eskalationssteuerung.
|
||||
Aussage: Das System soll gleichzeitige Bearbeitung eines Tickets durch mehrere Mitarbeiter über eine Sperrkennzeichnung verhindern und erlauben, einzelne Ticketinhalte als ausschließlich intern sichtbar zu kennzeichnen.
|
||||
Ergebnis: Ein gesperrtes Ticket zeigt den sperrenden Benutzer an; intern markierte Inhalte werden im Kundenportal nicht ausgeliefert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/Helpdesk.cs (Z. 49, 77, 98, 122, 126) - Begründung: Datenfelder direkt im Kernmodell.
|
||||
- [HYPOTHESE] Die serverseitige Durchsetzung der Sperre (Ablehnung konkurrierender Schreibzugriffe) wurde nicht im BL-Code verifiziert, nur das Datenfeld selbst - offen, ob rein UI-seitig oder auch serverseitig erzwungen.
|
||||
Prüfidee: Zwei Bearbeiter öffnen dasselbe Ticket; zweiter Bearbeiter erhält Hinweis auf Sperre durch ersten (LockUserName gesetzt).
|
||||
Tracelinks: StRS-015; SwRS-020
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-021
|
||||
Titel: Konfigurationsgesteuerte Änderbarkeit des Fakturierungsdatums
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (TimerBillingSettingsPageViewModel), Helpdesk-/Servicemitarbeiter
|
||||
Vorbedingung: Der Benutzer öffnet die Timer-Fakturierungs-Einstellungen und aktiviert "UseBillingDate".
|
||||
Fakt: UpdateBillingDateIsEnabled liest je nach ReceiptKind entweder CentronCache.Instance.ReceiptSettings.CanChangeDateInInvoices oder ...CanChangeDateInDeliveryLists; ist der Wert falsch/nicht gesetzt, wird das Datumsfeld deaktiviert und ein Hinweistext mit dem exakten, belegtypabhängigen Rechtenamen angezeigt.
|
||||
Aussage: Das System soll die Eingabe des Fakturierungsdatums im Timer-Fakturierungs-Assistenten in Abhängigkeit von einer zentralen, belegtypspezifischen Einstellung sperren und den Benutzer im Sperrfall über den Namen der fehlenden Berechtigung informieren.
|
||||
Ergebnis: Benutzer ohne die passende Einstellung/Berechtigung sehen ein deaktiviertes Datumsfeld mit erklärendem Hinweistext statt einer unspezifischen Fehlermeldung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, UpdateBillingDateIsEnabled (Diff Commit baa9e7bd9b) - Begründung: Vollständige, neu eingeführte Logik.
|
||||
Prüfidee: Für ReceiptKind=InvoiceClass mit CanChangeDateInInvoices=false → BillingDateIsEnabled=false, Hinweistext enthält "der Rechnung"; für DeliveryListClass entsprechend "des Lieferscheins".
|
||||
Tracelinks: StRS-016; SwRS-021
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-022
|
||||
Titel: Historisierung des Artikeleinkaufspreises bei Lagerbuchung
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (ArticleBL)
|
||||
Vorbedingung: Eine Lagerbuchung mit Einkaufspreisbezug wird auf einen Artikel im Hauptlager gebucht.
|
||||
Fakt: UpdateArticlePurchasePriceThroughStockBooking verschiebt vor jeder Preisänderung RawEk1(+Date+ObjectI3D+ObjectKind) nach RawEk2, bevor RawEk1 mit dem neuen Buchungspreis, aktuellem Datum und Referenz auf den auslösenden Beleg überschrieben wird; Haupt- und Nebenlagerbuchungen (storage.I3D<=0 vs. >0) werden unterschiedlich behandelt.
|
||||
Aussage: Das System soll bei jeder einkaufspreisrelevanten Lagerbuchung im Hauptlager den vorherigen Rohpreis samt Quellbeleg-Referenz in ein zweites Feld verschieben, bevor der neue Preis übernommen wird.
|
||||
Ergebnis: Zu jedem Artikel sind die zwei zuletzt gebuchten Rohpreise inkl. auslösendem Beleg nachvollziehbar; der Verkaufspreis (PurchasePrice) wird nur bei tatsächlicher Preisänderung aktualisiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs (Z. 3602-3652) - Begründung: Vollständige Update-Logik mit Unterscheidung geänderter/unveränderter Preis.
|
||||
Prüfidee: Wareneingang mit Preis A, danach Wareneingang mit Preis B auf denselben Artikel im Hauptlager → nach zweiter Buchung: RawEk1=B, RawEk2=A.
|
||||
Tracelinks: StRS-017; SwRS-022
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-023
|
||||
Titel: Lizenzbasierte Policy-Autorisierung auf API-Ebene
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (CentronHostedHandler)
|
||||
Vorbedingung: Ein API-Endpunkt ist mit der Policy "CentronHosted" geschützt.
|
||||
Fakt: CentronHostedHandler.HandleRequirementAsync ruft LicenseManager.Instance.HasLicense(LicenseGuids.CentronInternal) auf und lässt die Anforderung nur bei vorhandener Lizenz erfolgreich sein (context.Succeed).
|
||||
Aussage: Das System soll den Zugriff auf bestimmte, als "CentronHosted" markierte API-Bereiche zusätzlich zur Benutzerauthentifizierung an eine mandantenweite Lizenzprüfung koppeln.
|
||||
Ergebnis: Mandanten ohne die betreffende Lizenz erhalten auch bei korrekt authentifiziertem und berechtigtem Benutzer keinen Zugriff auf diese Endpunkte.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/CentronHostedAuthorization.cs (Z. 8-25) - Begründung: Vollständige, aktive Policy-Handler-Implementierung.
|
||||
- [SEKUNDÄR] src/backend/Centron.Interfaces/Administration/Logins/LicenseGuids.cs - Begründung: Katalog aller referenzierbaren Lizenzen (Kontext für weitere, gleichartige Policies).
|
||||
Prüfidee: Mandant ohne Lizenz CentronInternal ruft geschützten Endpunkt mit gültigem JWT eines berechtigten Benutzers auf → Zugriff dennoch verweigert.
|
||||
Tracelinks: StRS-018, StRS-019; SwRS-023
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-024
|
||||
Titel: Strikte JWT-Bearer-Validierung für moderne API-Clients
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (Centron.Host)
|
||||
Vorbedingung: Ein Client sendet einen Bearer-Token im Authorization-Header.
|
||||
Fakt: TokenValidationParameters setzt ValidateIssuer, ValidateAudience, ValidateLifetime, ValidateIssuerSigningKey, RequireSignedTokens, RequireExpirationTime und ValidateTokenReplay jeweils auf true (Z. 193-203); Ereignisse werden über LoggingJwtBearerEvents protokolliert.
|
||||
Aussage: Das System soll JWT-Bearer-Tokens vollständig gegen Aussteller, Zielgruppe, Gültigkeitsdauer, Signatur und Wiedereinspielung (Replay) prüfen, bevor ein Client als authentifiziert gilt.
|
||||
Ergebnis: Abgelaufene, falsch signierte, für eine andere Zielgruppe ausgestellte oder wiedereingespielte Tokens werden zurückgewiesen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs (Z. 188-205) - Begründung: Vollständige, aktive Konfiguration aller Validierungsparameter.
|
||||
Prüfidee: Manuell abgelaufener JWT wird bei Aufruf eines geschützten Endpunkts mit 401 abgelehnt (ValidateLifetime).
|
||||
Tracelinks: StRS-019; SwRS-024
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-025
|
||||
Titel: Getrennte Authentifizierungskanäle für Desktop-Client und CentronNexus
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (Centron.Host), Externes System (CentronNexus)
|
||||
Vorbedingung: Ein WPF-Client bzw. die CentronNexus-Webanwendung nimmt Kontakt zur zentralen API auf.
|
||||
Fakt: Neben JWT-Bearer wird ein proprietäres "Centron Ticket"-Schema registriert (AddCentronTicket) sowie eine eigene Authorization-Policy "SecretKey" mit SecretKeyRequirement(nexusConnectionKey) speziell für die Nexus-Anbindung definiert.
|
||||
Aussage: Das System soll für den historischen Desktop-Client, moderne Clients und die interne Service-zu-Service-Kommunikation mit CentronNexus jeweils eigenständige, zweckgebundene Authentifizierungsmechanismen bereitstellen statt eines einzigen universellen Verfahrens.
|
||||
Ergebnis: Ein Kompromittieren eines Kanals (z. B. des Nexus-SecretKey) gefährdet nicht automatisch die anderen Authentifizierungswege.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Host/CentronHost.cs (Z. 186-187, 207-213) - Begründung: Explizite, parallele Registrierung mehrerer Schemata/Policies.
|
||||
Prüfidee: Ein gültiger SecretKey ohne gültiges JWT erlaubt Zugriff auf ausschließlich SecretKey-geschützte Endpunkte, nicht auf JWT-geschützte Endpunkte (und umgekehrt).
|
||||
Tracelinks: StRS-019; SwRS-025
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-026
|
||||
Titel: Kombinierbare, kumulative Rechteanforderungen auf Controller- und Action-Ebene
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: Ein Controller trägt ein Autorisierungsattribut und eine einzelne Action trägt ein weiteres.
|
||||
Fakt: Laut Dokumentation und Attributarchitektur (TypeFilterAttribute-basiert) werden Filter aus Controller- und Action-Ebene kumulativ angewendet ("Requires BOTH SETTINGS (from controller) AND ADVANCED_SETTINGS").
|
||||
Aussage: Das System soll es erlauben, Basisrechte auf Controller-Ebene zu definieren und einzelne Actions mit zusätzlichen, kumulativ zu erfüllenden Rechten zu versehen.
|
||||
Ergebnis: Eine Action innerhalb eines rechtegeschützten Controllers kann strengere Anforderungen stellen als der Controller selbst, aber nicht schwächere.
|
||||
Belege:
|
||||
- [SEKUNDÄR] src/webservice/Centron.Controllers/Authorization/README.md (Z. 54-83) - Begründung: Dokumentiertes, aber nicht am Live-Code nachvollzogenes Verhalten (Kombination mehrerer TypeFilterAttribute ist Standard-ASP.NET-Core-Verhalten, hier nicht separat im Framework-Code verifiziert).
|
||||
Prüfidee: Controller mit [AuthorizeUserRight(SETTINGS)] und Action mit zusätzlichem [AuthorizeUserRight(ADVANCED_SETTINGS)]: Benutzer mit nur SETTINGS erhält 403 auf dieser Action.
|
||||
Tracelinks: StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: [HYPOTHESE] - nur SEKUNDÄR-Beleg (Dokumentation), keine PRIMÄR-Verifikation im Rahmen dieser Analyse; Filterkombinationsverhalten ist ASP.NET-Core-Standardverhalten, aber projektspezifisch nicht am Code bestätigt.
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-027
|
||||
Titel: Konfigurierbares Mandanten-Branding im Webportal (BrandingConfig)
|
||||
Ebene: SyRS
|
||||
Typ: Portabilität (ISO 25010: Anpassbarkeit)
|
||||
Akteur: System (CentronNexus)
|
||||
Vorbedingung: Für einen Mandanten ist eine BrandingConfig hinterlegt und der Beleg trägt ein MandatorImage.
|
||||
Fakt: WebReceiptOverview.razor injiziert IOptionsSnapshot<BrandingConfig> und bindet Receipt.MandatorImage bedingt (nur wenn vorhanden und nicht leer) als Logo ein.
|
||||
Aussage: Das System soll das Erscheinungsbild des Kundenportals über eine pro Mandant austauschbare Konfiguration (mindestens Logo) steuern, ohne dass eine Codeänderung nötig ist.
|
||||
Ergebnis: Unterschiedliche Mandanten können ohne Deployment-Änderung unterschiedlich gebrandete Web-Angebots-Seiten ausliefern.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor (Z. 12, 27, 38-42) - Begründung: Direkte Code-Evidenz der Konfigurationsinjektion und bedingten Anzeige.
|
||||
Prüfidee: Wechsel der BrandingConfig für einen Mandanten führt ohne Neubau der Anwendung zu geändertem Logo auf der Web-Angebots-Seite.
|
||||
Tracelinks: StRS-020; SwRS-017
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-028
|
||||
Titel: Feste Serverzeitzone Europe/Berlin (Portabilität/Internationalisierung)
|
||||
Ebene: SyRS
|
||||
Typ: Portabilität (ISO 25010: Anpassbarkeit)
|
||||
Akteur: System (Deployment)
|
||||
Vorbedingung: Der Webservice-Container wird gestartet.
|
||||
Fakt: Das Dockerfile setzt ENV TZ=Europe/Berlin fest im Container-Image (Z. 51), nicht konfigurierbar zur Laufzeit ohne Image-Änderung.
|
||||
Aussage: Das System soll (im aktuellen Deploymentmodell) mit einer fest im Container-Image verankerten Zeitzone betrieben werden.
|
||||
Ergebnis: Zeitstempel serverseitiger Verarbeitung basieren implizit auf Europe/Berlin; ein Betrieb für Mandanten in anderen Zeitzonen ohne eigenes Image ist nicht vorgesehen. [HYPOTHESE: Auswirkung auf fachliche Zeitstempel (z. B. CreatedAt) nicht verifiziert, nur die Container-Konfiguration selbst.]
|
||||
Belege:
|
||||
- [SEKUNDÄR] docker/c-entron-webservice/Dockerfile (Z. 51) - Begründung: Konfigurationsartefakt, keine Laufzeit-Verifikation im Rahmen dieser Analyse möglich.
|
||||
Prüfidee: Deployment desselben Images für einen Mandanten in einer anderen Zeitzone → Serverzeit bleibt Europe/Berlin (durch Log-Zeitstempel im Container zu verifizieren).
|
||||
Tracelinks: StRS-020
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-029
|
||||
Titel: Caching der Benutzerrechte zur Performance-Optimierung
|
||||
Ebene: SyRS
|
||||
Typ: Performance-Effizienz (ISO 25010)
|
||||
Akteur: System (AppRightsBL)
|
||||
Vorbedingung: HasUserRight/HasWebAccountRight wird für denselben Benutzer wiederholt aufgerufen.
|
||||
Fakt: Beide Methoden verwenden Session.Advanced.Cache.GetOrAdd mit einem benutzerspezifischen Cache-Key ("AllRightsFromAppUser{id}" bzw. "AllRightsFromWebAccount{id}"), sodass die zugrunde liegende SQL-Abfrage nicht bei jedem Rechtecheck erneut ausgeführt wird.
|
||||
Aussage: Das System soll wiederholte Rechteprüfungen innerhalb derselben Session performant durch Zwischenspeicherung der vollständigen Rechteliste eines Benutzers realisieren, statt bei jeder Prüfung erneut die Datenbank abzufragen.
|
||||
Ergebnis: Die Anzahl der SQL-Roundtrips für Rechteprüfungen ist unabhängig von der Anzahl der HasUserRight-Aufrufe innerhalb einer Session (amortisiert auf einen Abruf je Benutzer).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 646, 674) - Begründung: Direkte Cache-Nutzung im produktiven Prüfpfad.
|
||||
Prüfidee: Performance-Test: N aufeinanderfolgende HasUserRight-Aufrufe für denselben Benutzer erzeugen genau einen SQL-Query (Query-Zähler-Messung).
|
||||
Tracelinks: StRS-001; SwRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-030
|
||||
Titel: Containerisierte, selbstständige Server-Bereitstellung (Portabilität)
|
||||
Ebene: SyRS
|
||||
Typ: Portabilität (ISO 25010)
|
||||
Akteur: System (Deployment)
|
||||
Vorbedingung: Der Webservice-Teil wird für den produktiven Betrieb gebaut.
|
||||
Fakt: Mehrstufiges Dockerfile baut mit .NET-10-SDK auf Alpine Linux, veröffentlicht self-contained (`dotnet publish ... --self-contained true`), und läuft auf einem schlanken .NET-10-Runtime-Alpine-Image; Server-seitige Schriftarten/ICU-Daten werden nachinstalliert (fontconfig, msttcorefonts) für PDF-/Report-Erzeugung außerhalb von Windows.
|
||||
Aussage: Das System soll den Backend-/API-Teil unabhängig vom Windows-Betriebssystem containerisiert und selbstständig lauffähig (self-contained) bereitstellen können.
|
||||
Ergebnis: Der Webservice-Teil kann in einer Linux-Container-Umgebung ohne separate .NET-Runtime-Installation betrieben werden.
|
||||
Belege:
|
||||
- [PRIMÄR] docker/c-entron-webservice/Dockerfile (vollständige Datei) - Begründung: Konkretes, aktiv genutztes Build-Artefakt.
|
||||
Prüfidee: Start des gebauten Images ohne vorinstallierte .NET-Runtime auf dem Host → Anwendung startet erfolgreich (self-contained-Nachweis).
|
||||
Tracelinks: StRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-031
|
||||
Titel: Kommerzielle Abhängigkeit von DevExpress-Komponenten (Wartbarkeit)
|
||||
Ebene: SyRS
|
||||
Typ: Wartbarkeit (ISO 25010)
|
||||
Akteur: System, Systemadministrator (Lizenzverwaltung)
|
||||
Vorbedingung: Build/Betrieb des Systems erfordert eine gültige DevExpress-Lizenz.
|
||||
Fakt: Docker-Build injiziert einen DevExpress-Lizenzschlüssel (`dx_license`) als Build-Argument; PdfSigningBL nutzt DevExpress.Office.DigitalSignatures/Tsp/Pdf direkt als Kernabhängigkeit für PDF-Signatur.
|
||||
Aussage: Das System soll für PDF-Erzeugung, -Signatur und vermutlich weitere Report-/UI-Funktionen von einer kommerziellen Drittanbieter-Bibliothek (DevExpress) abhängen, deren Lizenzverfügbarkeit Build und Betrieb voraussetzt.
|
||||
Ergebnis: Ein Build/Deployment ohne gültige DevExpress-Lizenz ist nicht funktionsfähig für die betroffenen Funktionsbereiche.
|
||||
Belege:
|
||||
- [PRIMÄR] docker/c-entron-webservice/Dockerfile (Z. 21-23) - Begründung: Expliziter Lizenzschlüssel-Mechanismus im Build.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs (Z. 12-14, Imports) - Begründung: Direkte Nutzung DevExpress-spezifischer Namespaces in fachlicher Kernlogik.
|
||||
Prüfidee: Build ohne gültigen DevExpress-Lizenzschlüssel → Build- oder Laufzeitfehler in signatur-/reportbezogenen Funktionen (nicht im Rahmen dieser statischen Analyse ausführbar getestet).
|
||||
Tracelinks: StRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-032
|
||||
Titel: Microsoft-SQL-Server als alleinige Datenhaltung mit gemischtem ORM-/Raw-SQL-Zugriff
|
||||
Ebene: SyRS
|
||||
Typ: Kompatibilität (ISO 25010)
|
||||
Akteur: System (DAO-Schicht)
|
||||
Vorbedingung: Jede Geschäftslogikoperation mit Datenzugriff.
|
||||
Fakt: Zahlreiche BL-Klassen verwenden parallel NHibernate/LINQ (`Session.GetSession().Query<T>()`) und direkten Raw-SQL-Zugriff (`Session.Advanced.RawSqlAccess`) mit T-SQL-spezifischer Syntax (`dbo.`-Präfixe, `IIF(...)`-Funktion); Beispiel-Connection-String im Dockerfile referenziert explizit "SA"/"Server=...".
|
||||
Aussage: Das System soll auf Microsoft SQL Server als alleinige unterstützte Datenbank ausgelegt sein und nutzt sowohl ORM-Abstraktion als auch direkten, dialektspezifischen SQL-Zugriff innerhalb derselben Fachlogik-Klassen.
|
||||
Ergebnis: Ein Wechsel der Datenbanktechnologie würde signifikante Anpassungen in der Geschäftslogikschicht selbst erfordern (keine reine Persistenzschicht-Kapselung), da Raw-SQL direkt in *BL-Klassen eingebettet ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (Z. 97-101, 115-119) - Begründung: Raw-T-SQL direkt in Fachlogik.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs (Z. 7295-7300, IIF-Funktion) - Begründung: MSSQL-spezifische Funktion in Raw-SQL.
|
||||
- [SEKUNDÄR] docker/c-entron-webservice/Dockerfile (Z. 55, auskommentierter Beispiel-Connection-String) - Begründung: Bestätigt MSSQL als Zieldatenbank im Deployment-Kontext.
|
||||
Prüfidee: Migration einer einzelnen BL-Klasse mit Raw-SQL auf eine andere Datenbank ohne Anpassung der SQL-Strings schlägt fehl (z. B. IIF ist keine Standard-SQL-Funktion in PostgreSQL).
|
||||
Tracelinks: StRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-033
|
||||
Titel: Standardisierte Fehlerrückgabe über Result/Result\<T\> statt Exceptions
|
||||
Ebene: SyRS
|
||||
Typ: Wartbarkeit (ISO 25010)
|
||||
Akteur: System
|
||||
Vorbedingung: Eine Fachoperation kann einen erwartbaren Fehlerfall haben (z. B. fehlendes Recht, Konflikt).
|
||||
Fakt: Nahezu alle untersuchten BL-Methoden (AppRightsBL, ReceiptBL, DataSecurityBL, PdfSigningBL) geben Result bzw. Result\<T\> mit Status, Meldungstext und optionalem MessageCode (z. B. RightCheckFailed, ChangedByOtherInstance, BadRequest) zurück, statt Exceptions für Fachfehler zu werfen.
|
||||
Aussage: Das System soll erwartbare Fachfehler durchgängig über einen einheitlichen Result-Rückgabetyp mit maschinenlesbarem MessageCode kommunizieren, um Aufrufern (API-Controller, UI) eine konsistente Fehlerbehandlung zu ermöglichen.
|
||||
Ergebnis: Aufrufende Schichten (Controller, ViewModels) können anhand von Status/MessageCode einheitlich reagieren, ohne Exception-Handling für Fachfälle zu benötigen.
|
||||
Belege:
|
||||
- [PRIMÄR] durchgängiges Muster in allen in dieser Analyse gelesenen BL-Dateien (siehe Belege StRS-001 bis StRS-018) - Begründung: Konsistente Verwendung über mehrere unabhängige Module hinweg spricht für einen bewussten Architekturstandard.
|
||||
- [SEKUNDÄR] src/backend/Centron.Interfaces/Results/DefaultMessageCodes.cs (Datei referenziert, nicht vollständig gelesen) - Begründung: Zentrale Definition der MessageCodes bestätigt Systematik.
|
||||
Prüfidee: Statische Codeanalyse: Anteil von BL-Methoden mit Rückgabetyp Result/Result\<T\> an rechteprüfenden/validierenden Methoden (Stichprobe zeigt nahezu 100 % in den analysierten Klassen).
|
||||
Tracelinks: StRS-001, StRS-006 bis StRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-034
|
||||
Titel: Legacy-Datenbankschema mit historisch deutschen Tabellen-/Feldnamen
|
||||
Ebene: SyRS
|
||||
Typ: Wartbarkeit (ISO 25010)
|
||||
Akteur: System
|
||||
Vorbedingung: Zugriff auf das zugrunde liegende relationale Schema.
|
||||
Fakt: Raw-SQL-Fragmente referenzieren Tabellen wie Sichtrus/Sichgrup/Sichmemb (Rechte), Ang/Auf/Lief/Abhol (Angebote/Aufträge/Lieferscheine/Abholscheine), Kunden/Kreditor (Kunden/Lieferanten); Kommentar in CentronObjectKindNumeric.cs (Z. 14) bestätigt: neue .NET-Konstanten werden parallel zu einem weiterhin aktiven Delphi-System ab Wert 7600000 vergeben.
|
||||
Aussage: Das System soll auf einem historisch gewachsenen, ursprünglich für ein Delphi-Vorgängersystem konzipierten Datenbankschema mit weiterhin aktiver Zwei-System-Konstantenvergabe aufsetzen.
|
||||
Ergebnis: Für eine Neuimplementierung ist relevant, dass das bestehende Schema nicht domänensprachlich (Englisch) konsistent benannt ist und ein Parallelbetrieb mit einem Nicht-.NET-System (Delphi) berücksichtigt werden muss.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/CentronObjectKindNumeric.cs (Z. 6-14) - Begründung: Expliziter Warnkommentar zur Nummernvergabe zwischen zwei Systemen.
|
||||
- [SEKUNDÄR] Tabellennamen in Raw-SQL, z. B. AppRightsBL.cs Z. 97-101, DataSecurityBL.cs Z. 79 - Begründung: Konkrete Belege der historischen Namensgebung.
|
||||
Prüfidee: n/a (dokumentierender Befund, keine funktionale Prüfidee) - relevanter Hinweis für Datenmigrationsplanung.
|
||||
Tracelinks: StRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# Traceability-Tabelle
|
||||
|
||||
Forward-Traceability (StRS → SyRS → SwRS) und Rückverweis auf den primären Artefaktbeleg. Vollständige Begründungen stehen in den jeweiligen Anforderungsblöcken in StRS.md/SyRS.md/SwRS.md; diese Tabelle dient dem schnellen Überblick und dem Konsistenzcheck (siehe Analysebericht.md).
|
||||
|
||||
| StRS-ID | SyRS-ID | SwRS-ID | Primärer Artefaktbeleg |
|
||||
|---|---|---|---|
|
||||
| StRS-001 | SyRS-001 | SwRS-001 | AppRightsBL.cs, HasUserRight (Z. 644-649) |
|
||||
| StRS-001 | SyRS-001 | SwRS-002 | AppRightsBL.cs, GetAllAppRightsFromUser (Z. 651-664) |
|
||||
| StRS-001 | SyRS-002 | SwRS-003 | AuthorizeUserRightAttribute.cs (Z. 29-56) |
|
||||
| StRS-001 | SyRS-026 | — | Authorization/README.md (Z. 54-83) [HYPOTHESE] |
|
||||
| StRS-001 | SyRS-029 | SwRS-001 | AppRightsBL.cs (Z. 646, 674) |
|
||||
| StRS-002 | SyRS-003 | SwRS-004 | ReceiptBL.cs, CanUserViewReceipt (Z. 10297-10311) |
|
||||
| StRS-003 | SyRS-004 | SwRS-005 | ReceiptBL.cs, CanUserEditReceipt (Z. 10272-10295) |
|
||||
| StRS-004 | SyRS-005 | SwRS-006 | AppRightsBL.cs, GetAssignableAdminRightI3Ds/DeleteRightGroup (Z. 348-374, 714-759) |
|
||||
| StRS-005 | SyRS-006 | SwRS-007 | AppRightsBL.cs, Region "Logging" (Z. 761-858) |
|
||||
| StRS-006 | SyRS-007 | SwRS-008 | ReceiptBase.cs (vollständig) |
|
||||
| StRS-006 | SyRS-008 | SwRS-009 | ReceiptBL.cs, GetReceiptForwardedInto (Z. 9938-9946) |
|
||||
| StRS-007 | SyRS-009 | SwRS-010 | ReceiptBL.cs, UpdateReceiptIsPaid (Z. 4936-4937) |
|
||||
| StRS-008 | SyRS-010 | SwRS-011 | NumberGroupBL.cs, FindNextNumber (Z. 94-134) |
|
||||
| StRS-008 | SyRS-010 | SwRS-012 | NumberGroupBL.cs, GetNextNumber (Z. 62-92) |
|
||||
| StRS-008 | SyRS-011 | SwRS-013 | NumberGroupBL.cs, CreateNumberGroups (Z. 154-197); ReceiptBL.cs (Z. 7265-7285) |
|
||||
| StRS-009 | SyRS-012 | SwRS-014 | ReceiptBL.cs, SaveReceipt (Z. 3557-3578, 4884-4885, 4939-4940) |
|
||||
| StRS-010 | SyRS-013 | SwRS-010 | ReceiptBL.cs, UpdateReceiptIsPaid (Z. 4920-4934) |
|
||||
| StRS-011 | SyRS-014 | SwRS-015 | ReceiptBL.cs (Z. 3266-3274) |
|
||||
| StRS-012 | SyRS-015 | SwRS-016 | PdfSigningBL.cs (Z. 29-90) |
|
||||
| StRS-012 | SyRS-031 | — | Dockerfile (Z. 21-23); PdfSigningBL.cs (Imports Z. 12-14) |
|
||||
| StRS-013 | SyRS-016 | SwRS-017 | WebReceiptOverview.razor (Z. 1-90) |
|
||||
| StRS-014 | SyRS-017 | SwRS-018 | DataSecurityBL.cs (Z. 34-62) |
|
||||
| StRS-014 | SyRS-018 | SwRS-018 | DataSecurityBL.cs, DataSecurityExecuteCleanUp (Z. 64-70) |
|
||||
| StRS-015 | SyRS-019 | SwRS-019 | HelpdeskStateBase.cs (vollständig) |
|
||||
| StRS-015 | SyRS-020 | SwRS-020 | Helpdesk.cs (Z. 49, 77, 90-92, 95-98, 122, 126) |
|
||||
| StRS-016 | SyRS-021 | SwRS-021 | TimerBillingSettingsPageViewModel.cs, UpdateBillingDateIsEnabled (Commit baa9e7bd9b) |
|
||||
| StRS-017 | SyRS-022 | SwRS-022 | ArticleBL.cs, UpdateArticlePurchasePriceThroughStockBooking (Z. 3602-3652) |
|
||||
| StRS-018 | SyRS-023 | SwRS-023 | CentronHostedAuthorization.cs (Z. 10-25) |
|
||||
| StRS-018 | SyRS-030 | — | docker/c-entron-webservice/Dockerfile (vollständig) |
|
||||
| StRS-018 | SyRS-032 | — | AppRightsBL.cs (Z. 97-101); ReceiptBL.cs (Z. 7295-7300) |
|
||||
| StRS-018 | SyRS-034 | SwRS-028 | CentronObjectKindNumeric.cs (Z. 6-14) |
|
||||
| StRS-019 | SyRS-024 | SwRS-024 | CentronHost.cs (Z. 184-205) |
|
||||
| StRS-019 | SyRS-025 | SwRS-025 | CentronHost.cs (Z. 186-187, 207-213, 216) |
|
||||
| StRS-020 | SyRS-027 | SwRS-017 | WebReceiptOverview.razor (Z. 12, 27, 38-42) |
|
||||
| StRS-020 | SyRS-028 | — | Dockerfile (Z. 51) [HYPOTHESE, Auswirkung auf Fachzeitstempel] |
|
||||
| — (querschnittlich) | SyRS-033 | SwRS-026 | Konstruktormuster in AppRightsBL.cs, NumberGroupBL.cs u. a. |
|
||||
| — (querschnittlich) | SyRS-033 | SwRS-027 | Result/Result\<T\>-Verwendung, durchgängig |
|
||||
|
||||
## Hinweise zur Tabelle
|
||||
|
||||
- Zeilen mit "—" in der SwRS-Spalte kennzeichnen SyRS-Anforderungen auf reiner Deployment-/Architektur-Ebene (Containerisierung, DB-Technologie, Zeitzonenkonfiguration), zu denen im Rahmen dieser Iteration keine gesonderte, methodengenaue SwRS-Anforderung erhoben wurde (siehe Analysebericht.md, Lücken).
|
||||
- SwRS-010 erscheint zweimal (StRS-007 und StRS-010), da die zugrunde liegende Methode `UpdateReceiptIsPaid` beide Fachregeln (Status-Sperre und Alternativrecht) in einer Methode vereint – siehe Konsolidierungshinweis bei SyRS-009/SyRS-013.
|
||||
- SwRS-017 erscheint zweimal (StRS-013 und StRS-020), da dieselbe Komponente (WebReceiptOverview.razor) sowohl die Token-Routing- als auch die Branding-Anforderung erfüllt.
|
||||
- Zwei zusätzliche, nicht auf ein einzelnes StRS zurückführbare SyRS/SwRS-Paare (SyRS-033/SwRS-026/SwRS-027) betreffen ein querschnittliches Architekturmuster (BaseBL/DAOSession, Result-Typ), das allen fachlichen StRS-001 bis StRS-018 zugrunde liegt, und wird daher als "querschnittlich" statt einem einzelnen StRS zugeordnet ausgewiesen.
|
||||
|
||||
## Konsistenzcheck (siehe auch Analysebericht.md)
|
||||
|
||||
- Alle in StRS.md/SyRS.md/SwRS.md referenzierten IDs wurden gegen diese Tabelle abgeglichen. Keine doppelt vergebenen IDs innerhalb einer Ebene gefunden (StRS-001…020, SyRS-001…034, SwRS-001…028, jeweils lückenlos und einmalig vergeben).
|
||||
- Alle SwRS-Tracelinks referenzieren existierende SyRS-IDs; alle SyRS-Tracelinks referenzieren existierende StRS-IDs. Keine toten Verweise festgestellt.
|
||||
- Nicht jede SyRS-Anforderung besitzt eine SwRS-Entsprechung (siehe Hinweis oben) – dies ist als bewusste Scoping-Entscheidung, nicht als Fehler zu werten, und im Analysebericht.md als Lücke dokumentiert.
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
# Messprotokoll - V1 (Baseline, solo) - Prompt-Version 01, Lauf 8 (Lauf B)
|
||||
|
||||
> **Erste echte V1-Messung.** Agentenmodus `solo`: Der Lauf durfte keine Subagenten starten.
|
||||
> Die Laeufe 1-6 liefen faktisch mit eingebauten Subagenten und gehoeren zu **V1b**.
|
||||
>
|
||||
> **Parallelbetrieb:** Dieser Lauf lief zeitgleich mit `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173142_v3.2.0-496c`.
|
||||
> Beide Laeufe konkurrierten um CPU, Netzwerk und API-Kontingent. **Wanduhrzeit, `duration_ms`
|
||||
> und `duration_api_ms` sind dadurch verzerrt** und nicht mit seriellen Laeufen vergleichbar.
|
||||
> Tokens, Kosten, Anforderungsanzahl und Denials sind unverzerrt.
|
||||
|
||||
## Lauf
|
||||
- **Prompt-Datei:** `Versuche/Versuch_01/01_Prompt.md`
|
||||
- **SHA-256 (Prompt):** `1B0DB06B8E0A5B92A5EFBDBEC5A0C554351FC928A16AEF34AAD9EAA0893C02FF`
|
||||
(identisch zu allen bisherigen Laeufen)
|
||||
- **Startzeit:** 2026-08-25T17:32:10.1904139+02:00
|
||||
- **Endzeit:** 2026-08-25T17:56:03.4011565+02:00
|
||||
- **Dauer gesamt:** 00:23:53 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:23:52 (`duration_ms`) - API: 00:22:31
|
||||
- **Root-Verzeichnis:** `c:\DEV\MasterArbeit\QuellCode\CentronERP`
|
||||
- **Codebasis-Commit:** `79c1142f489a32ba6a4a4cb043fd7f8550a9f257` (dirty: nein)
|
||||
- **Snapshot-Zustand:** bereinigt von KI-Konfigurationen: **ja** (strenge Pruefung: 0 Treffer);
|
||||
Remote entkoppelt: **ja**
|
||||
- **Prompt-Repo-Commit:** `0ec86aed8cb8781054c86cbe0dd9f5eb0f7e5f05`
|
||||
|
||||
## Werkzeugkonfiguration
|
||||
- **Laufverzeichnis-ID:** `v3.2.0-2bc6`
|
||||
- **Ablage:** `Iteration 1/claude-sonnet-5/solo/high/`
|
||||
- **Parallele Laeufe:** ja - `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_173142_v3.2.0-496c`
|
||||
- **Skill-Version:** `3.2.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 ueber `--disallowedTools Task Agent Workflow`
|
||||
- **Effort:** `high` — **nicht zur Laufzeit gesetzt**, sondern aus der Sitzung geerbt und
|
||||
nachtraeglich aus dem Session-Transkript rekonstruiert (182 Nachrichten, durchgaengig `high`).
|
||||
`RawResult.json` enthaelt kein `effort`-Feld. Ab Skill-Version 3.4.0 wird der Wert per
|
||||
`--effort` explizit gesetzt.
|
||||
- **Modell:** `claude-sonnet-5` (vom Versuchsleiter vor dem Lauf gewaehlt); zusaetzlich
|
||||
`claude-haiku-4-5-20251001` fuer interne Hilfsaufrufe (4.193 Input-/20 Output-Tokens)
|
||||
- **Permission-Mode:** `acceptEdits`
|
||||
- **Toolfreigabe:** `--allowedTools "Bash" "PowerShell"`; `--disallowedTools` mit 36 Eintraegen
|
||||
(22 x `Bash(...)`, 11 x `PowerShell(...)`, 3 x Agentenwerkzeuge `Task`/`Agent`/`Workflow`)
|
||||
- **Isolationsmechanismus:** eingefrorener Codebasis-Snapshot ohne KI-Konfigurationen,
|
||||
zusaetzlich `--safe-mode` und `--strict-mcp-config`
|
||||
- **MCP-Server / Agentendateien:** keine - aus dem Snapshot entfernt, zusaetzlich `--safe-mode`
|
||||
- **Subagenten:** **0** (durch die Versuchsbedingung ausgeschlossen)
|
||||
- **Fast-Mode:** aus
|
||||
|
||||
## Verbrauch
|
||||
|
||||
### Hauptagent (`usage`)
|
||||
| Messgroesse | Wert |
|
||||
|---|---|
|
||||
| Input-Tokens | 214 |
|
||||
| Output-Tokens | 129.057 (davon 21.863 Thinking-Tokens) |
|
||||
| Cache-Write-Tokens | 232.328 |
|
||||
| Cache-Read-Tokens | 12.232.691 |
|
||||
| Agent-Turns | 107 |
|
||||
|
||||
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
|
||||
| Messgroesse | `claude-sonnet-5` | `claude-haiku-4-5-20251001` | Summe |
|
||||
|---|---:|---:|---:|
|
||||
| Input-Tokens | 214 | 4.193 | 4.407 |
|
||||
| Output-Tokens | 129.057 | 20 | 129.077 |
|
||||
| Cache-Write-Tokens | 232.328 | 0 | 232.328 |
|
||||
| Cache-Read-Tokens | 12.232.691 | 0 | 12.232.691 |
|
||||
| Tokens gesamt | 12.594.290 | 4.213 | **12.598.503** |
|
||||
|
||||
**Tokens gesamt: 12.598.503** (Summe aus Input, Output, Cache-Write und Cache-Read ueber alle Modelle; `total_cost_usd` steht weiterhin in `RawResult.json`)
|
||||
|
||||
Ohne Subagenten sind Haupt- und Gesamtwerte fuer `claude-sonnet-5` identisch - anders als in
|
||||
allen V1b-Laeufen, wo sie um bis zu Faktor 21,6 auseinanderlagen.
|
||||
|
||||
## Ergebnis
|
||||
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
|
||||
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
|
||||
- **Session-ID:** `d58ac933-39f7-4458-ad61-1325f2cbbf7f`
|
||||
- **Permission-Denials:** **0** - auch keine auf `Task`/`Agent`/`Workflow` (siehe Anmerkung 1)
|
||||
- **Kontrolle Agentenmodus:** `subagent_stats.spawned` = **0** - die Sperre hat gegriffen,
|
||||
der Lauf ist als V1-Messung gueltig
|
||||
- **Erzeugte Dateien:** alle 7 geforderten Artefakte in `Ergebnisse\`, **keine Fremddateien**
|
||||
|
||||
| Datei | Groesse | Inhalt |
|
||||
|---|---:|---|
|
||||
| `StRS.md` | 36.943 B | 20 Anforderungen |
|
||||
| `SyRS.md` | 48.640 B | 34 Anforderungen |
|
||||
| `SwRS.md` | 39.857 B | 28 Anforderungen |
|
||||
| `Traceability.md` | 5.316 B | 36 Datenzeilen |
|
||||
| `Hypothesen.md` | 5.341 B | 9 Inline-Markierungen `[HYPOTHESE]` |
|
||||
| `Glossar.md` | 6.879 B | Domaenenbegriffe |
|
||||
| `Analysebericht.md` | 16.541 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
|
||||
|
||||
Summe: **82 Anforderungen** ueber drei Ebenen.
|
||||
- **Root unveraendert:** 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`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 20 | 24,4 % |
|
||||
| SyRS | 34 | 41,5 % |
|
||||
| SwRS | 28 | 34,1 % |
|
||||
| **Gesamt** | **82** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| Sicherheit | 28 | 34,1 % |
|
||||
| Daten | 18 | 22,0 % |
|
||||
| funktional | 14 | 17,1 % |
|
||||
| Schnittstelle | 6 | 7,3 % |
|
||||
| Wartbarkeit (ISO 25010) | 3 | 3,7 % |
|
||||
| nicht-funktional | 2 | 2,4 % |
|
||||
| Daten (Zuverlässigkeit) | 2 | 2,4 % |
|
||||
| Portabilität (ISO 25010: Anpassbarkeit) | 2 | 2,4 % |
|
||||
| Wartbarkeit | 2 | 2,4 % |
|
||||
| Sicherheit (Nachvollziehbarkeit, ISO 25010: Sicherheit/Accountability) | 1 | 1,2 % |
|
||||
| (4 weitere) | 4 | 4,9 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 111 |
|
||||
| davon `PRIMÄR` | 91 (82,0 %) |
|
||||
| davon `SEKUNDÄR` | 15 (13,5 %) |
|
||||
| davon `KONTEXT` | 5 (4,5 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 80 (97,6 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 80 | 97,6 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 2 | 2,4 % |
|
||||
| als Workaround vermerkt | 3 | 3,7 % |
|
||||
| Konsolidierungskandidaten | 2 | 2,4 % |
|
||||
| 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** (40 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 82 von 82 mit Tracelinks (100,0 %) |
|
||||
|
||||
## Vergleich V1 (solo) gegen V1b (builtin)
|
||||
|
||||
| Messgroesse | **Lauf A (V1)** | **Lauf B (V1)** | V1b: Lauf 4 | Lauf 3 | Lauf 6 | Lauf 5 |
|
||||
|---|---:|---:|---:|---:|---:|---:|
|
||||
| Subagenten | **0** | **0** | 0 | 7 | 7 | 14 |
|
||||
| Anforderungen | **42** | **82** | 55 | 106 | 189 | 325 |
|
||||
| Tokens gesamt | **4.357.855** | **12.598.503** | 27.562.244 | 11.516.200 | 32.568.122 | 52.713.542 |
|
||||
| Output-Tokens | **70.749** | **129.077** | 121.989 | 229.997 | 466.115 | 1.266.149 |
|
||||
| Cache-Read | **4,12 M** | **12,23 M** | 27,18 M | 10,54 M | 30,78 M | 44,83 M |
|
||||
| Agent-Turns | **68** | **107** | 147 | 69 | 29 | 31 |
|
||||
| Denials | **0** | **0** | 0 | 0 | 0 | 1 |
|
||||
|
||||
## Anmerkungen/Auffaelligkeiten
|
||||
|
||||
1. **Keine Denials auf die gesperrten Agentenwerkzeuge - entgegen der Erwartung.** Im Skill war
|
||||
vermerkt, dass im Solo-Modus Denials auf `Task`/`Agent`/`Workflow` "erwartbar" seien. Beide
|
||||
Laeufe zeigen **0**. Gesperrte Werkzeuge werden dem Modell offenbar gar nicht erst angeboten;
|
||||
es plant von vornherein eine Einzelkontext-Strategie, statt zu delegieren und abgewiesen zu
|
||||
werden. Die Bedingung wirkt also ueber die Planung, nicht ueber Fehlversuche - methodisch die
|
||||
sauberere Variante. Der `Workflow`-Denial im Verifikationstest kam nur zustande, weil der
|
||||
Testprompt ausdruecklich zum Delegieren aufforderte.
|
||||
|
||||
2. **V1 ist erheblich guenstiger als V1b.** 2,20 und 12.598.503 Tokens gegenueber 6,82 bis 52.713.542 Tokens.
|
||||
Selbst der teurere der beiden V1-Laeufe kostet weniger als der guenstigste V1b-Lauf. Ursache
|
||||
ist der fehlende Subagenten-Overhead: Ohne parallele Kontexte entfaellt das mehrfache Einlesen
|
||||
derselben Artefakte, sichtbar an den deutlich niedrigeren Cache-Read-Tokens.
|
||||
|
||||
3. **V1 liefert weniger Anforderungen - aber die Streuung bleibt.** 42 gegenueber 82 zwischen zwei
|
||||
Laeufen derselben Bedingung ist Faktor 2,0. Das ist geringer als die Faktor-5,9-Streuung in
|
||||
V1b, aber immer noch zu gross, um aus zwei Messpunkten eine belastbare Aussage abzuleiten.
|
||||
Fuer eine Aussage "V1 liefert weniger als V1b" waeren mehr Laeufe je Bedingung noetig.
|
||||
|
||||
4. **Parallelbetrieb technisch fehlerfrei.** Beide Laeufe schrieben in getrennte Verzeichnisse mit
|
||||
eigenem `_meta` (eigene `before.txt`, eigener archivierter Prompt, eigene Zeitstempel). Keine
|
||||
Kollision, keine gegenseitige Ueberschreibung, beide Ergebnisverzeichnisse frei von
|
||||
Fremddateien, Root unveraendert. Das mit Skill-Version 3.1.0 eingefuehrte Verfahren
|
||||
funktioniert im Realbetrieb.
|
||||
|
||||
5. **Zeitangaben nicht fuer Laufzeitvergleiche verwenden.** Beide Laeufe konkurrierten um dieselbe
|
||||
Maschine. Lauf A brauchte 12:45, Lauf B 23:53 - der Unterschied ist nicht ohne Weiteres
|
||||
inhaltlich zu deuten, weil Lauf A frueher fertig war und Lauf B danach die Maschine allein
|
||||
hatte. Fuer Laufzeitvergleiche seriell messen.
|
||||
|
||||
6. **Manuelle Eingriffe waehrend des Laufs:** keine.
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"is_error":false,"duration_api_ms":1350716,"num_turns":107,"stop_reason":"end_turn","session_id":"d58ac933-39f7-4458-ad61-1325f2cbbf7f","total_cost_usd":4.671141199999999,"usage":{"input_tokens":214,"cache_creation_input_tokens":232328,"cache_read_input_tokens":12232691,"output_tokens":129057,"output_tokens_details":{"thinking_tokens":21863},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":232328,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":937,"cache_read_input_tokens":259639,"cache_creation_input_tokens":412,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":412},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4193,"outputTokens":20,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004293,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-sonnet-5":{"inputTokens":214,"outputTokens":129057,"cacheReadInputTokens":12232691,"cacheCreationInputTokens":232328,"webSearchRequests":0,"costUSD":4.6668482,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-sonnet-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":"## Zusammenfassung\n\nDie RRE-Analyse (Schritte 2–6) ist abgeschlossen. Alle sieben geforderten Dateien liegen im Ausgabeverzeichnis vor:\n\n- **StRS.md** (20 Anforderungen) – Akteure, Geschäftsziele, u.a. Rechtemodell, Belegkette, Belegnummernvergabe, DSGVO, digitale Signatur (C-Sign), Zeit-Fakturierung, Lizenzmodell\n- **SyRS.md** (34 Anforderungen) – Systemverhalten, API-Authentifizierung (JWT/Ticket/SecretKey), Schnittstellen, NFRs nach ISO 25010\n- **SwRS.md** (28 Anforderungen) – konkrete Klassen/Methoden (`AppRightsBL`, `ReceiptBL`, `NumberGroupBL`, `DataSecurityBL`, `PdfSigningBL` u.a.)\n- **Traceability.md**, **Hypothesen.md**, **Glossar.md**, **Analysebericht.md**\n\n**Konsistenzcheck bestanden:** keine doppelten IDs, keine unbelegten Anforderungen, keine toten Tracelinks (automatisiert gegengeprüft).\n\n**Wichtigster inhaltlicher Befund:** Die DSGVO-Massenbereinigung (`DataSecurityExecuteCleanUp`) ist im Code ein reiner Stub – prüft Rechte, löscht aber nichts (StRS-014/SwRS-018, `belegt; Workaround`).\n\n**Größte offene Lücke:** Die Codebasis ist mit >15.500 C#-Dateien so groß, dass diese Iteration nur ~13 gezielt priorisierte Schwerpunkte (Security, Belegwesen, Billing, DSGVO, Ticketing, Auth, Lizenzierung, Deployment) tief bzw. stichprobenartig abdecken konnte; alles Weitere (u.a. 464 WebServices-Dateien, WPF-Client, ~65 weitere BL-Module, CentronNexus im Detail) ist in Analysebericht.md explizit als \"nicht analysiert\" ausgewiesen statt stillschweigend übergangen.\n\nBemerkenswert für die Zielsetzung \"Web-/SaaS-Neuimplementierung\": Mit **CentronNexus** existiert bereits eine separate Blazor-Webanwendung (460 Razor-Dateien) für Kundenportal/Web-Angebote/digitale Signatur – ein Umstand, den ich als Ausgangsbasis statt \"grüne Wiese\" markiert habe.","ttft_ms":3625,"ttft_stream_ms":1380,"time_to_request_ms":36,"type":"result","duration_ms":1431592,"uuid":"159ccb0b-e593-441d-9b5e-42c99d4dbca6","queued_turn_count":0}
|
||||
+1425
File diff suppressed because it is too large
Load Diff
+66
@@ -0,0 +1,66 @@
|
||||
## Gefundene Anforderungen
|
||||
|
||||
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 20 | 24,4 % |
|
||||
| SyRS | 34 | 41,5 % |
|
||||
| SwRS | 28 | 34,1 % |
|
||||
| **Gesamt** | **82** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| Sicherheit | 28 | 34,1 % |
|
||||
| Daten | 18 | 22,0 % |
|
||||
| funktional | 14 | 17,1 % |
|
||||
| Schnittstelle | 6 | 7,3 % |
|
||||
| Wartbarkeit (ISO 25010) | 3 | 3,7 % |
|
||||
| nicht-funktional | 2 | 2,4 % |
|
||||
| Daten (Zuverlässigkeit) | 2 | 2,4 % |
|
||||
| Portabilität (ISO 25010: Anpassbarkeit) | 2 | 2,4 % |
|
||||
| Wartbarkeit | 2 | 2,4 % |
|
||||
| Sicherheit (Nachvollziehbarkeit, ISO 25010: Sicherheit/Accountability) | 1 | 1,2 % |
|
||||
| (4 weitere) | 4 | 4,9 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 111 |
|
||||
| davon `PRIMÄR` | 91 (82,0 %) |
|
||||
| davon `SEKUNDÄR` | 15 (13,5 %) |
|
||||
| davon `KONTEXT` | 5 (4,5 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 80 (97,6 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 80 | 97,6 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 2 | 2,4 % |
|
||||
| als Workaround vermerkt | 3 | 3,7 % |
|
||||
| Konsolidierungskandidaten | 2 | 2,4 % |
|
||||
| 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** (40 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 82 von 82 mit Tracelinks (100,0 %) |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+132
@@ -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_173143_sonnet5_solo_v3.2.0-2bc6\Ergebnisse\`.
|
||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T17:56:03.4011565+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T17:32:10.1904139+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# Subagenten-Aufrufe
|
||||
|
||||
Session `d58ac933-39f7-4458-ad61-1325f2cbbf7f`, Transkript `d58ac933-39f7-4458-ad61-1325f2cbbf7f.jsonl`.
|
||||
|
||||
`subagent_stats`: **0** Subagenten gesamt, davon **0** von Subagenten gestartet (max_depth 0). Direkt vom Hauptagenten erwartet: **0**. Im Transkript gefunden: **0**.
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
# Analysebericht
|
||||
|
||||
Reverse Requirements Engineering der c-entron.NET ERP-Suite — Iteration 01 (Baseline, Prompt-only, keine Agentendateien/MCP-Server). Dieser Bericht dokumentiert Scope-Umsetzung, Analysetiefe je Bereich, den Konsistenzcheck über das gesamte Anforderungs-Set sowie eine Selbstbewertung gemäß Auftrag.
|
||||
|
||||
## 1. Untersuchungsgegenstand: Größenordnung
|
||||
|
||||
Die Codebasis wurde zu Beginn quantitativ erfasst (Stand: Arbeitsverzeichnis `C:\DEV\MasterArbeit\QuellCode\CentronERP`, Branch `main`):
|
||||
|
||||
| Kennzahl | Wert |
|
||||
|---|---|
|
||||
| C#-Dateien (`*.cs`) | 16.063 |
|
||||
| XAML-Dateien (`*.xaml`) | 1.233 |
|
||||
| Razor/CSHTML-Dateien | 491 |
|
||||
| Projekte laut `src/`-Struktur | ~30 (backend, centron/WPF, nexus/Blazor, webservice, apis, shared) |
|
||||
| Test-Projekte | 8 (`tests/backend`, `tests/apis`, `tests/shared`, `tests/Centron.Tests.Integration`, `tests/Centron.Tests.EndToEnd`, `tests/CentronNexusTests`, `tests/PlaywrightTests`) |
|
||||
| Dokumentationsdateien in `docs/` | ~45 Markdown-Dateien mit z. T. sehr hoher fachlicher Dichte |
|
||||
|
||||
**Konsequenz für die Methodik:** Eine vollständige, gleichrangige Tiefenanalyse aller Module (wie im Scope-Vorgabe „bewusst keine Modulbeschränkung“ gefordert) ist in einer einzelnen Iteration bei dieser Größenordnung nicht mit vollständiger Codeabdeckung leistbar. Der Auftrag selbst sieht dies vor („Priorisiere die Analysetiefe selbstständig, dokumentiere aber... welche Bereiche wie tief analysiert wurden“) – die vorliegende Iteration wählt daher bewusst **9 fachliche Domänen als Tiefenbohrungen** (siehe Abschnitt 2) statt einer flächendeckenden, aber notwendigerweise oberflächlichen Erfassung aller Module.
|
||||
|
||||
## 2. Abgedeckte Bereiche und Analysetiefe
|
||||
|
||||
| Domäne | Tiefe | Kernartefakte gelesen | Repräsentiert in |
|
||||
|---|---|---|---|
|
||||
| A. Rechte-/Berechtigungsverwaltung | **Tief** (Primärquelle vollständig gesichtet) | `UserRightsConst.cs` (Kopf + Stichproben, 2819 Zeilen gesamt), `CentronRights.md` (vollständig), `docs/guides/development/check-userrights.md`, `add-a-new-right.md` | StRS-001/002, SyRS-001/002, SwRS-001-003 |
|
||||
| B. Belegwesen (Receipts, generisch) | **Mittel** (Basisklasse vollständig, Architektur über Doku) | `ReceiptBase.cs` (vollständig), `ReceiptState.cs` (vollständig), `receipts-backend-architecture.md` (vollständig) | StRS-003/004, SyRS-003-005, SwRS-004/005 |
|
||||
| C. Web-Angebot & C-Sign (digitale Signatur) | **Tief** (mehrere Kernklassen vollständig/weitgehend gelesen) | `WebReceiptOverview.razor` (vollständig, 1283 Zeilen), `ReceiptBL.cs` (Ausschnitt Zeilen 6170-6320, gezielt um AcceptWebReceipt-Familie), `WebReceiptState.cs`, `SharedDocumentSignPage.razor` (Zeilen 1-120), `ReceiptPdfDocument.cs` (Ausschnitt) | StRS-005/006/007, SyRS-006/007/008, SwRS-006-012 |
|
||||
| D. Verträge (Contracts) | **Oberflächlich/stichprobenhaft** (nur Dokumentation + Datei-Existenzprüfung, kein Volltext-Code) | `contracts-backend.md` (vollständig), Datei-Existenz von `ReceiptContract.cs`/`ReceiptContractBL.cs` verifiziert, **Inhalt dieser Dateien nicht gelesen** | StRS-008/009, SyRS-009/010, SwRS-013/014 |
|
||||
| E. Zeiterfassung / Timer-Billing | **Tief, aber schmal** (ein konkreter Anwendungsfall vollständig über Commit-Diff belegt, Modul insgesamt nicht breiter untersucht) | Vollständiger Diff des Commits `baa9e7bd9b` (`TimerBillingSettingsPageView.xaml`, `...ViewModel.cs`) | StRS-010, SyRS-011, SwRS-015/016 |
|
||||
| F. Helpdesk/Ticketsystem | **Mittel** (eine BL-Klasse vollständig, Rechte-Dokumentation vollständig, Suchfilter-Implementierung nicht analysiert) | `HelpdeskStatusBL.cs` (vollständig, 106 Zeilen), `CentronRights.md` Abschnitt Helpdesk (vollständig) | StRS-011/012, SyRS-012, SwRS-017/018 |
|
||||
| G. EDI (Lieferanten-Datenaustausch) | **Oberflächlich** (Dokumentation vollständig, Code nur Signatur-Ebene und Dateisystem-Struktur) | `edi-architecture.md` (vollständig), Signatur von `ApplyDistriToCentron` (1 Zeile Code), Dateisystem-Verifikation der 7 Partial-Class-Dateien | StRS-013/014, SyRS-013/014, SwRS-019 |
|
||||
| H. Authentifizierung (OIDC) & Lizenzierung | **Tief** (Kernklassen vollständig gelesen) | `OpenIdConnectAuthenticator.cs` (vollständig, 76 Zeilen), `TicketBL.cs` (gezielte Ausschnitte inkl. Konstanten und zwei Kernmethoden), `LicenseManager.cs` (Methodensignaturen), `docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md` (vollständig), `docs/reference/security/licensing-system.md` (vollständig) | StRS-015/016, SyRS-015-017, SwRS-020-023 |
|
||||
| I. WPF-Ribbon-Usability | **Sehr oberflächlich** (nur Commit-Metadaten, kein XAML-Volltext) | Commit-Message und `git show --stat` von `8dd17c7d12`; `ModuleResources.xaml` **nicht geöffnet** | StRS-017, SyRS-018, SwRS-024 |
|
||||
|
||||
### Nicht bzw. nur namentlich betrachtete Bereiche (bewusste Lücken)
|
||||
|
||||
Die folgenden, im Scope grundsätzlich eingeschlossenen Bereiche wurden in dieser Iteration **nicht** untersucht (weder Code noch Dokumentation gezielt gelesen) und tragen daher keine eigenen Anforderungen in StRS/SyRS/SwRS:
|
||||
|
||||
- **Lagerhaltung/Warenwirtschaft** (Artikelstamm, Bestandsführung) – nur indirekt über `RIGHT_ARTIKELSTAMM`/`RIGHT_LIEFERANTENSTAMM` in `UserRightsConst.cs` sichtbar geworden.
|
||||
- **Buchhaltung/Finanzbuchhaltung im engeren Sinn** (Kontenrahmen, Journalbuchungen, `Centron.APIs.FinAPI`) – nicht untersucht.
|
||||
- **c-entron Nexus WebCart/Shop-Funktion** – nur über `docs/README.md` (Nexus-Regeln) am Rande erwähnt.
|
||||
- **Outlook-Add-In (`CentronNexus.OutlookAddIn`)** – nicht untersucht.
|
||||
- **Versandintegrationen** (`Centron.Api.Gls`, `Centron.Api.Shipcloud`) – nicht untersucht.
|
||||
- **ZUGFeRD/E-Rechnung im Detail** (`docs/guides/development/xrechnung.md`, `docs/reference/zugferd-*`) – Dateien identifiziert, nicht gelesen.
|
||||
- **Deployment/Installer** (`deployment/WixSharpInstaller`, Docker-Compose-Definitionen) – Verzeichnisstruktur nur oberflächlich gesichtet (Abschnitt „Top-level layout“), keine Datei geöffnet; keine NFR-Anforderungen zu Deployment/Betrieb abgeleitet, obwohl der Auftrag dies explizit vorsieht („Leite Betriebs- und Sicherheitsanforderungen gezielt auch aus... Deployment-Skripten... ab“) – **dies ist eine bewusste, zu dokumentierende Lücke dieser Iteration**.
|
||||
- **DAO/Mapping-Schicht im Detail** (`Centron.DAO/Mappings/**`) – nur exemplarisch für zwei Felder referenziert (`ReceiptPdfDocumentMaps.cs`), nicht systematisch analysiert.
|
||||
- **CentronNexus (Blazor) darüber hinaus** – nur die drei Web-Angebot-/Signatur-Seiten betrachtet, nicht das gesamte Nexus-Portal (z. B. Helpdesk-Web-Ansicht, Rechnungs-Übersicht für Kunden).
|
||||
|
||||
## 3. Konsistenzcheck über das gesamte Anforderungs-Set
|
||||
|
||||
Durchgeführt nach Fertigstellung von StRS.md, SyRS.md, SwRS.md und Traceability.md.
|
||||
|
||||
### 3.1 Doppelte oder mehrfach vergebene IDs
|
||||
Geprüft per Extraktion aller `^ID:`-Zeilen aus den drei Dokumenten und Duplikatsuche.
|
||||
|
||||
- **Ergebnis: Keine Duplikate.** StRS-001..017 (17, lückenlos), SyRS-001..019 (19, lückenlos), SwRS-001..024 (24, lückenlos) – jede ID kommt genau einmal als definierende `ID:`-Zeile vor.
|
||||
|
||||
### 3.2 Anforderungen ohne Beleg
|
||||
Geprüft per Zählung der `Belege:`-Blöcke gegen die Anzahl `ID:`-Zeilen je Dokument.
|
||||
|
||||
- StRS.md: 17 IDs, 17 `Belege:`-Blöcke, 17 mit mindestens einer `[PRIMÄR]`-Zeile.
|
||||
- SyRS.md: 19 IDs, 19 `Belege:`-Blöcke, 12 mit mindestens einer `[PRIMÄR]`-Zeile (die übrigen 7 sind bewusst als `[HYPOTHESE]` bzw. rein `[SEKUNDÄR]`/`[KONTEXT]`-gestützt gekennzeichnet, siehe Status-Feld).
|
||||
- SwRS.md: 24 IDs, 24 `Belege:`-Blöcke, 22 mit mindestens einer `[PRIMÄR]`-Zeile.
|
||||
- **Ergebnis: Keine Anforderung ohne mindestens einen Beleg.** Die Belegpflicht wurde für alle 60 Anforderungen eingehalten.
|
||||
|
||||
### 3.3 Risikobasierte Evidenzanforderung (Sicherheit, Abrechnung, Rechte)
|
||||
Zusätzliche, über die Grundprüfung hinausgehende Prüfung gemäß Auftrag: Anforderungen der Typen „Sicherheit“ sowie zu Abrechnung/Fakturierung und Berechtigungen müssen mindestens einen `PRIMÄR`-Beleg führen oder als `[HYPOTHESE]` gekennzeichnet sein.
|
||||
|
||||
- Geprüft wurden alle Anforderungen mit `Typ: Sicherheit` sowie thematisch Abrechnung/Rechte (Domänen A, C [Signaturteil], E, H).
|
||||
- **Korrektur während der Erstellung:** StRS-002 führte ursprünglich fälschlich ein Dokumentationsdokument (`CentronRights.md`) als `[PRIMÄR]` statt eine Code-Konstante; dies wurde korrigiert (`UserRightsConst.cs` ist nun der `[PRIMÄR]`-Beleg, `CentronRights.md` `[SEKUNDÄR]`).
|
||||
- Verbleibende Anforderungen ohne `PRIMÄR`-Beleg in diesen Risikokategorien (SyRS-002, SyRS-005, SyRS-009, SyRS-010, SyRS-014, SyRS-019, StRS-009, StRS-014, SwRS-014, SwRS-023) sind **alle** korrekt mit `Status: HYPOTHESE` gekennzeichnet. **Ergebnis: Regel eingehalten.**
|
||||
|
||||
### 3.4 Tracelinks auf nicht existierende IDs
|
||||
Geprüft per Extraktion aller `Tracelinks:`-Zeilen und Abgleich jeder referenzierten ID gegen die tatsächlich vergebenen IDs.
|
||||
|
||||
- **Ursprünglich gefunden (vor Korrektur):** 5 fehlerhafte Tracelinks in StRS.md – teils Verweise auf nicht existierende SwRS-Nummern (`SwRS-025`, `SwRS-028`, es gab zum Zeitpunkt der Erstellung nur bis `SwRS-024`), teils domänenfremde Falschverweise (z. B. StRS-010 [Timer-Billing] verwies versehentlich auf `SwRS-018` [Helpdesk-Löschschutz] statt auf die korrekten `SwRS-015`/`SwRS-016`).
|
||||
- **Alle 5 Fehler wurden vor Abgabe korrigiert** (siehe Diff-Historie dieser Iteration). Nach Korrektur: alle referenzierten IDs existieren.
|
||||
- **Verbleibende, bewusst dokumentierte Lücke (keine Fehlreferenz, sondern fehlende Rückverknüpfung):** StRS-016 wird von keiner SyRS-Anforderung exklusiv über `Tracelinks` zurückreferenziert (SyRS-015/SyRS-017 verweisen nur auf StRS-015). Dies ist in `Traceability.md` unter „Bekannte Konsolidierungs-/Struktur-Hinweise“ offengelegt, nicht stillschweigend belassen.
|
||||
|
||||
### 3.5 Konsolidierungskandidaten (Querschnittsprüfung)
|
||||
Im Rahmen der Erstellung wurden folgende Konsolidierungsfälle identifiziert und im Feld `Konsolidierung` der jeweiligen Anforderung vermerkt:
|
||||
|
||||
- **StRS-006/StRS-007**: Signaturpflichtiger vs. signaturfreier Web-Angebots-Abschluss sind im Code zwei getrennte Methoden (`AcceptWebReceipt` / `AcceptWebReceiptWithoutSignature`) statt eines parametrisierten Ablaufs – Konsolidierungskandidat für die Zielarchitektur.
|
||||
- **SwRS-003**: Drei parallele, unabhängig gepflegte Rechteprüfungs-APIs (UI-Cache, Modul-Helper, BL-Methode) für dasselbe fachliche Konzept.
|
||||
|
||||
## 4. Selbstbewertung
|
||||
|
||||
### 4.1 Welche Module wurden vollständig, welche nur stichprobenhaft, welche gar nicht analysiert?
|
||||
|
||||
- **Vollständig (im Sinne von: zentrale Klasse(n) im Volltext gelesen und gegen Dokumentation abgeglichen):** Rechteverwaltung (Struktur), Web-Angebot/C-Sign-Kernablauf, Helpdesk-Status-Verwaltung, OIDC-Authentifizierung, Ticket-Sitzungsverwaltung.
|
||||
- **Stichprobenhaft (Dokumentation vollständig gelesen, Code nur an einzelnen, gezielt gesuchten Stellen verifiziert):** Belegwesen allgemein, Verträge/Kontingente, EDI, Timer-Billing (nur ein Feature-Ausschnitt über einen einzelnen Commit).
|
||||
- **Gar nicht analysiert:** Lagerhaltung, Finanzbuchhaltung im engeren Sinn, WebCart/Shop, Outlook-Add-In, Versandintegrationen, ZUGFeRD/E-Rechnung im Detail, Deployment/Installer/Docker, DAO/Mapping-Schicht systematisch, der überwiegende Teil des Nexus-Portals.
|
||||
- Insgesamt wurden von 16.063 C#-Dateien schätzungsweise **unter 0,5 %** im Volltext gelesen; die Aussagekraft der Spezifikation stützt sich stark auf die vorhandene, ungewöhnlich detaillierte Entwicklerdokumentation in `docs/`, die als SEKUNDÄR-Beleg dient und stichprobenartig gegen den Code verifiziert wurde.
|
||||
|
||||
### 4.2 Wo war der Beleg dünn (hoher Anteil SEKUNDÄR/KONTEXT bzw. HYPOTHESE)?
|
||||
|
||||
- **Verträge/Kontingente (Domäne D):** Fast ausschließlich auf `contracts-backend.md` gestützt; kein einziges Vertrags-BL-Code-Zitat im Volltext. Höchstes Risiko für Abweichung zwischen Dokumentation und tatsächlichem Codestand in dieser Spezifikation.
|
||||
- **EDI (Domäne G):** Nur die zentrale Dispatch-Signatur wurde verifiziert; sämtliche Aussagen zu Fehlerbehandlung, Format-Fallbacks und lieferantenspezifischen Eigenheiten stammen ausschließlich aus `edi-architecture.md`.
|
||||
- **Versionierungsmechanismus (`AssetHeadDAO.SaveAssetVersion`, StRS-004/SyRS-005):** Zentral für die Audit-Trail-Aussage, aber nie im Code geöffnet.
|
||||
- **Ribbon-Usability-Fix (Domäne I):** Ausschließlich Commit-Message, kein XAML-Code gesehen.
|
||||
|
||||
### 4.3 Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?
|
||||
|
||||
1. **Code-Verifikation der Vertragsdomäne** (`ReceiptContract.cs`, `ReceiptContractBL.cs`, `AutomaticFacturaBL.Contracts.cs`) im Volltext, insbesondere die Kontingent-Berechnungslogik – höchste fachliche Kritikalität (Abrechnung) bei aktuell schwächster Codeverifikation.
|
||||
2. **Verifikation der Rechte-Filterdurchsetzung** auf Datenbankabfrage-Ebene (z. B. Helpdesk-Suchfilter) – sicherheitsrelevant, aktuell nur als Konstanten-Existenz, nicht als durchgesetzte Query-Logik belegt (SyRS-002).
|
||||
3. **EDI-Fehlerbehandlung im Code** verifizieren, insbesondere Komsa-Rechnungsausschluss (StRS-014) und Teilverarbeitungsverhalten (SyRS-014).
|
||||
4. **Deployment-/Betriebs-NFRs nachholen**: Diese Iteration hat trotz expliziter Auftragsvorgabe keine Anforderungen aus `deployment/`, `docker/` oder Logging-Konfiguration abgeleitet – klare Lücke gegenüber dem Auftrag, die in Iteration 02 vorrangig zu schließen ist.
|
||||
5. **Breiteres Sampling weiterer Module** (Lager, Finanzbuchhaltung, Versand, Nexus-Portal jenseits Web-Angebot), um die im Scope geforderte Gleichrangigkeit aller Module schrittweise besser anzunähern.
|
||||
6. **AssetHeadDAO.SaveAssetVersion** und mindestens eine `SaveReceipt*Repository`-Klasse im Volltext lesen, um die zentrale, mehrfach als Workaround gekennzeichnete Persistenz-Doppelspurigkeit (SyRS-004) tatsächlich am Code zu bestätigen statt nur über Dokumentation.
|
||||
|
||||
## 5. Zusammenfassung
|
||||
|
||||
Diese Iteration liefert eine **belastbare, aber bewusst schmale Tiefenbohrung** durch neun fachliche Domänen einer sehr großen Codebasis, mit vollständiger Einhaltung der formalen Belegpflicht, der risikobasierten Evidenzanforderung und einer lückenlosen, im Rahmen des Konsistenzchecks korrigierten Traceability. Sie ersetzt **nicht** eine vollständige Erfassung aller Module der c-entron.NET-Suite und ist explizit als Ausgangspunkt für iterative Vertiefung (Schritt 7 der RRE-Methodenkette: fachliche Validierung, sowie Folge-Iterationen gemäß Abschnitt 4.3) zu verstehen.
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
# Glossar
|
||||
|
||||
Domänenbegriffe, wie sie in StRS/SyRS/SwRS verwendet werden. Deutsche Fachbegriffe sind maßgeblich; technische Bezeichner (Klassen, Tabellen, Spalten) bleiben im Original.
|
||||
|
||||
| Begriff | Definition | Technischer Bezug |
|
||||
|---|---|---|
|
||||
| **Beleg (Receipt)** | Sammelbegriff für alle kaufmännischen Dokumente des Vertriebsprozesses: Angebot, Auftrag, Lieferschein, Rechnung, Vertrag, Gutschrift, Abholliste. Alle Belegtypen teilen eine gemeinsame Kopf-/Positions-Struktur. | `ReceiptBase`, `*Kopf`/`*Pos`-Tabellen |
|
||||
| **Belegkopf (Kopf)** | Header-Datensatz eines Belegs mit Kunde, Datum, Status, Summen. | `AngKopf`, `AufKopf`, `RechKopf`, `VertragKopf`, `LiefKopf`, `GutKopf`, `AbholKopf` |
|
||||
| **Belegposition (Pos)** | Einzelne Zeile/Position innerhalb eines Belegs (Artikel, Titelzeile, Rabatt, Summenzeile etc.). | `AngPos`, `AufPos`, `RechPos`, `VertragPos`, ... |
|
||||
| **I3D** | Primärschlüsselkonvention der Codebasis: durchgängiger Identity-Spaltenname für Entitäten (statt z. B. `Id`). | Spalte `I3D` in nahezu allen Tabellen |
|
||||
| **ObjectKind / AnlageArt** | Numerischer Diskriminator, der den konkreten Belegtyp referenzübergreifend identifiziert (z. B. 1=Angebot, 4=Rechnung, 22=Vertrag). Wird für generische Referenzen (`ObjectI3D`+`ObjectKind`, `AnlageI3D`+`AnlageArt`) genutzt. | `CentronObjectKindNumeric`, Tabelle `AnlageLog` |
|
||||
| **Versionierung (Versions-Tabellen)** | Für jeden Belegtyp existiert eine `*Versions`-Tabelle als 1:1-Kopie der Basistabelle, die bei jeder Änderung einen Snapshot ablegt (Audit-Trail, Rollback). | `AngKopfVersions`, `VertragPosVersions`, `AssetHeadDAO.SaveAssetVersion` |
|
||||
| **Web-Angebot (WebOffer / Web-Beleg)** | Variante eines Angebots, die dem Kunden über das Kundenportal (c-entron Nexus) zur Online-Ansicht, -Änderung und -Annahme bereitgestellt wird, optional mit digitaler Signatur. | `WebReceiptOverview.razor`, `WebReceiptState`, `ReceiptPdfDocument` |
|
||||
| **C-Sign** | Interner Produktname für die Funktion zur digitalen Signatur von Dokumenten (Eingeben/Hochladen/Zeichnen einer Unterschrift) im Zusammenhang mit der Web-Angebot-Annahme. | `SharedDocumentSignPage.razor`, `SignatureType` |
|
||||
| **Änderungsanfrage (Change Request)** | Vom Kunden im Web-Angebot vorgenommene Änderung (z. B. Mengenänderung, Positionsart), die vor der endgültigen Annahme als offene Anfrage gespeichert wird. | `WebReceiptItemChangeRequest`, `ChangeRequestKind` |
|
||||
| **Vertrag (Contract)** | Spezialisierter Beleg für wiederkehrende Leistungen/Abrechnung (Wartungsverträge, Service-Level-Verträge), inkl. Abrechnungsintervall, Kontingent und Geräteanbindung. | `ReceiptContract`, `VertragKopf` |
|
||||
| **Kontingent (Contingent)** | Im Vertrag hinterlegtes Volumen (Stunden oder Betrag), das durch Leistungen/Zeiten verbraucht wird und dessen Verbrauch/Saldo überwacht wird. | `ContingentUsedHours`, `ContingentBalanceUsedAmount` |
|
||||
| **RMM** | Remote Monitoring and Management – externe Systeme zur Fernüberwachung von Kundengeräten, deren Daten in die automatische Vertragsabrechnung einfließen. | `AutomaticFacturaBL.Contracts`, Doku `Contract-Billing-RMM-Article-Logic.md` |
|
||||
| **Automatische Fakturierung** | Vom System zeitgesteuert ausgelöste Rechnungserstellung aus Verträgen entsprechend Abrechnungsintervall. | `AutomaticFacturaBL` |
|
||||
| **Zeiterfassung / Timer** | Erfassung von Arbeitszeiten (z. B. auf Helpdesk-Tickets), die später fakturiert werden können. | Modul `Finances/TimerBilling` |
|
||||
| **Belegdatum (Billing Date)** | Datum, das beim automatisierten Timer-Billing für neu erzeugte Rechnungen/Lieferscheine verwendet wird; seine Änderbarkeit ist rechtegesteuert. | `TimerBillingSettingsPageViewModel`, `ReceiptSettingsDTO.CanChangeDateInInvoices` |
|
||||
| **Recht (User Right)** | Diskrete Berechtigung, die einem Benutzer über eine Gruppenzuordnung erteilt wird und den Zugriff auf Module/Aktionen steuert. Rechte sind in der Datenbanktabelle `Sichrech` hinterlegt und über `UserRightsConst` referenziert. | `UserRightsConst.cs`, Tabelle `Sichrech`, `AppRightsBL.CheckRightsFromUser` |
|
||||
| **Einschränkendes Recht (Restricting Right)** | Sonderfall eines Rechts, das den Wirkungsbereich eines übergeordneten Rechts einschränkt (z. B. „nur eigene Filiale“, „nur eigene Tickets“), anstatt eine neue Fähigkeit freizuschalten. | z. B. `SHOW_HELPDESK_ONLY_OWN`, `SHOW_HELPDESK_ONLY_OWN_BRANCH` |
|
||||
| **Filiale (Branch)** | Organisatorische Einheit, der Benutzer, Belege und Daten zugeordnet sein können; Grundlage vieler einschränkender Rechte. | `BranchI3D`, `SHOW_HELPDESK_ONLY_OWN_BRANCH` |
|
||||
| **Helpdesk / Ticket** | Vorgang im Support-Modul zur Erfassung, Bearbeitung und Abrechnung von Kundenanfragen inkl. Status, Zeiten, Checklisten. | `HelpdeskCompact`, `HelpdeskState`, `HelpdeskStatusBL` |
|
||||
| **Ticket-Status (HelpdeskState)** | Frei durch den Anwender konfigurierbarer, benannter Zustand eines Tickets (kein festverdrahtetes Enum); referenziert u. a. für „geschlossen“ und „Standardstatus nach Öffnen“ über Anwendungseinstellungen. | `HelpdeskState`, `AppSettingsConst.HelpdeskClosedState` |
|
||||
| **C-FLOW** | Interner Produktname für Ticketvorlagen-Funktionalität im Helpdesk (automatisierte Ticketerstellung nach Muster). | `UserRightsConst...CFlow`, Doku `automatic-helpdesk-creation-templates.md` |
|
||||
| **EDI (Electronic Data Interchange)** | Automatisierter elektronischer Austausch von Bestell-, Auftragsbestätigungs-, Liefer- und Rechnungsdaten mit Lieferanten in lieferantenspezifischen Formaten. | `SupplierEdiBL`, `EdiDataType` |
|
||||
| **Lizenz (License)** | GUID-basierte Freischaltung einzelner Funktionen oder ganzer Anwendungen (Applications) für einen Kunden, optional mit Anzahl-, Datums- oder Versionsbeschränkung, zentral verwaltet über einen Lizenzserver. | `LicenseManager`, `LicenseGuids.cs` |
|
||||
| **Applikation (ApplicationKind)** | Teilmenge der Lizenzen, die zum Login am Webservice berechtigen (z. B. c-entron.NET, Service-Board, Outlook-Add-In). | `ApplicationKind.cs` |
|
||||
| **Ticket (Auth Ticket)** | Nach erfolgreichem Login ausgestellter, zeitlich befristeter Sitzungsnachweis (Hash), der bei weiteren Webservice-Aufrufen zur Authentifizierung übermittelt wird. Nicht zu verwechseln mit Helpdesk-„Ticket“. | `TicketBL`, Tabelle `Ticket` |
|
||||
| **Anmeldung mit Microsoft (OIDC-Login)** | Alternative Authentifizierungsmethode über Microsoft Entra ID (OpenID Connect/MSAL), bei der ein Microsoft-ID-Token gegen ein c-entron-Ticket getauscht wird. | `OpenIdConnectAuthenticator`, `OpenIdConnectSubjectIdentifier` |
|
||||
| **Ribbon** | Haupt-Navigationsleiste der WPF-Oberfläche (DevExpress RibbonControl) zur Auswahl von Modulen/Tabs. | `ModuleResources.xaml` |
|
||||
| **c-entron Nexus** | Blazor-Server-basiertes Kundenportal („c-entron Web“), über das externe Nutzer (Kunden, Weblogins) u. a. Web-Angebote einsehen/annehmen. | `src/nexus/CentronNexus` |
|
||||
| **Mandant / Branding** | Betreiberspezifische Kennzeichnung (Logo, Farben, Rechtstexte) der Nexus-Oberfläche für White-Label-Auslieferung. | `BrandingConfig` |
|
||||
|
||||
*Hinweis:* Weitere, seltener verwendete Fachbegriffe werden bei ihrem ersten Auftreten direkt im jeweiligen Anforderungsdokument (StRS/SyRS/SwRS) erläutert, sofern sie nicht in diese Tabelle aufgenommen wurden.
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
# Hypothesen
|
||||
|
||||
Sammlung aller mit `[HYPOTHESE]` gekennzeichneten Aussagen aus StRS.md, SyRS.md und SwRS.md, mit der jeweils offenen Frage, die zur Bestätigung/Widerlegung geklärt werden müsste. Sortiert nach Anforderungs-ID.
|
||||
|
||||
| ID | Aussage (verkürzt) | Offene Frage zur Bestätigung |
|
||||
|---|---|---|
|
||||
| StRS-009 | Kontingent-Grenzwertüberschreitung löst automatisiert Zusatzabrechnung/Warnung aus. | Muss im Code von `ReceiptContractBL`/`ContractContingentBalanceCalculation()` bzw. `ContingentLimitKinds` verifiziert werden: Wird bei Überschreitung tatsächlich eine Aktion ausgelöst, oder nur ein Datenfeld gesetzt, das erst durch einen weiteren manuellen Schritt zu einer Abrechnung führt? |
|
||||
| StRS-014 | Lieferant „Komsa“ verarbeitet keine elektronischen Rechnungen; die Codebasis enthält für diesen Fall keine entsprechende Methode. | Direkter Vergleich von `SupplierEdiBL.Komsa.cs` mit `SupplierEdiBL.Also.cs`/`.Alltron.cs` (die laut Doku Invoice-Support haben): Fehlt dort tatsächlich eine `ReadKomsaInvoice`-artige Methode? |
|
||||
| SyRS-002 | Serverseitige Query-Filter werden bei einschränkenden Rechten (z. B. „nur eigene Filiale“) automatisch ergänzt. | Muss in der konkreten Such-/Filterimplementierung (z. B. `HelpdeskBL`-Suchmethoden oder zugehörige `SearchFilter`-Klassen) verifiziert werden: Erfolgt die Einschränkung serverseitig in der Datenbankabfrage oder nur clientseitig/nachträglich in der UI? Letzteres wäre ein Sicherheitsrisiko (Information Disclosure via direktem API-Aufruf). |
|
||||
| SyRS-005 | `AssetHeadDAO.SaveAssetVersion` kopiert bei jeder Änderung alle Spalten vollständig in die Versionstabelle. | Der Methodenkörper von `AssetHeadDAO.SaveAssetVersion` wurde nicht gelesen; zu klären, ob die Kopie tatsächlich generisch (reflection-/spaltenlistenbasiert) oder je Belegtyp hartkodiert erfolgt, und ob Sonderfälle (z. B. Blob-/Bildfelder) ausgenommen sind. |
|
||||
| SyRS-009 | Ein Hintergrunddienst/Scheduler löst die automatische Vertragsabrechnung periodisch aus. | Welcher konkrete Dienst (`Centron.Host.WindowsService`? ein Script-/Cronjob-Mechanismus?) ruft `AutomaticFacturaBL` auf, und in welchem Intervall? Bisher nur als Konzept aus `contracts-backend.md` übernommen. |
|
||||
| SyRS-010 | Kontingentverbrauch wird bei jeder abrechnungsrelevanten Belegänderung neu berechnet. | Exakte Trigger-Punkte (welche Events lösen `UpdateContractContingentBalanceCalculationForReceiptChange()` aus?) und Rundungs-/Berechnungsformel nicht im Code verifiziert. |
|
||||
| SyRS-014 | Fehlerhafte EDI-Einzeldatensätze werden übersprungen, ohne die gesamte Dateiverarbeitung abzubrechen. | Konkretes Fehlerverhalten in `ApplyDistriToCentron`/den lieferantenspezifischen `Read*`-Methoden nicht im Code nachvollzogen; zu klären, ob ein Parse-Fehler in einer Zeile die gesamte Datei oder nur den betroffenen Datensatz betrifft. |
|
||||
| SyRS-019 | `AllowSendingEmailToExternalAddresses` in `DeveloperSecurity.cs` ist zur Laufzeit oder nur durch Neukompilierung änderbar; Schutz gilt nur für Debug-Builds. | `DeveloperSecurity.cs` wurde in dieser Iteration nicht geöffnet; zu klären, wie der Schalter tatsächlich gesetzt wird und ob es weitere Sicherheitsnetze für Release-Builds gibt. |
|
||||
| SwRS-011 | Bei abgelaufenem Signatur-Token erscheint dieselbe „Ungültiger Link“-Meldung wie bei nie existierendem Token. | `SharedDocumentSignPage.razor` wurde nur in den ersten 120 Zeilen gelesen; zu prüfen, ob der Ladefehlerpfad zwischen „abgelaufen“ und „ungültig/nicht gefunden“ unterscheidet. |
|
||||
| SwRS-014 | `MandatI3D` löst eine tatsächliche SEPA-XML-Exportlogik mit Fristenprüfung aus. | Zugehörige SEPA-Exportklasse(n) wurden nicht identifiziert/gelesen; nur der Feldname aus der Dokumentation bekannt. |
|
||||
| SwRS-023 | Der 24-Stunden-Sonderfall (`TicketExpire24HoursInMinutes`) sowie der konfigurierbare Fall in `TicketBL.GetExpireDate` sind jeweils an einen konkreten `ApplicationKind`-Wert gebunden. | Die switch-Bedingungen (welcher `ApplicationKind` welchen Zweig auslöst) wurden nicht zeilengenau exzerpiert; Code an `TicketBL.cs` Zeilen 136-163 müsste vollständig mit den umgebenden `case`-Werten gelesen werden. |
|
||||
|
||||
## Hinweis zur Verwendung
|
||||
|
||||
Diese Hypothesen sind **keine falschen Aussagen**, sondern Aussagen, für die in dieser Iteration kein hinreichend starker (PRIMÄR-)Beleg im Code selbst gefunden bzw. verifiziert wurde – meist, weil sie ausschließlich aus Entwicklerdokumentation stammen, deren Übereinstimmung mit dem tatsächlichen Code-Stand nicht in jedem Fall geprüft wurde, oder weil die referenzierte Methode aus Zeitgründen nicht bis zum Ende gelesen wurde. Sie sind vorrangige Kandidaten für Verifikation in einer Folge-Iteration (siehe Selbstbewertung in [Analysebericht.md](Analysebericht.md)) und für die fachliche Validierung durch Domänenexperten (Schritt 7 der RRE-Methodenkette).
|
||||
+400
@@ -0,0 +1,400 @@
|
||||
# Stakeholder Requirements Specification (StRS)
|
||||
|
||||
Fachliche Sicht auf die c-entron.NET ERP-Suite gemäß ISO/IEC/IEEE 29148:2018. Anforderungen dieser Ebene beschreiben Ziele und Bedürfnisse der Stakeholder (Vertrieb, Kundendienst, Buchhaltung, IT-Administration, Endkunde), unabhängig von der technischen Umsetzung. Jede StRS-Anforderung wird in SyRS.md und SwRS.md konkretisiert.
|
||||
|
||||
Zu Begriffen siehe [Glossar.md](Glossar.md). Zur Methodik (Belegklassen PRIMÄR/SEKUNDÄR/KONTEXT, `[HYPOTHESE]`) siehe [Analysebericht.md](Analysebericht.md).
|
||||
|
||||
## Akteursübersicht
|
||||
|
||||
| Akteur | Beschreibung | Beleg |
|
||||
|---|---|---|
|
||||
| Vertriebsmitarbeiter | Erstellt/bearbeitet Angebote, Aufträge, Verträge | `ReceiptView.xaml`, `UserRightsConst.Sales.*` |
|
||||
| Kunde (Web-Login) | Externer Nutzer, der über c-entron Nexus Web-Angebote einsieht, ändert, annimmt/ablehnt | `WebReceiptOverview.razor` |
|
||||
| Support-/Helpdesk-Mitarbeiter | Bearbeitet Tickets, erfasst Zeiten | `CentronRights.md` Abschnitt „Helpdesk“ |
|
||||
| Buchhaltung/Fakturierung | Verantwortlich für Rechnungsstellung, Vertragsabrechnung, Zahlungsbedingungen | `ReceiptContractBL`, `AutomaticFacturaBL` |
|
||||
| IT-/Systemadministrator | Verwaltet Benutzer, Rechte, Lizenzen, Systemeinstellungen | `UserRightsConst.cs`, `LicenseManager` |
|
||||
| Einkauf/Wareneingang | Verarbeitet Lieferantendaten (Bestellungen, Auftragsbestätigungen, Lieferungen, Rechnungen) über EDI | `SupplierEdiBL` |
|
||||
| Externes Lieferantensystem | Sendet/empfängt strukturierte Handelsdokumente (OpenTrans, ALSO, Herweck, Komsa, Alltron, ZUGFeRD) | `docs/reference/edi/edi-architecture.md` |
|
||||
| Microsoft Entra ID (externer Identitätsanbieter) | Authentifiziert Benutzer alternativ zum internen Login | `OpenIdConnectAuthenticator.cs` |
|
||||
| Lizenzserver (Betreiber) | Zentrale Quelle der Wahrheit für verkaufte Lizenzen/Features | `docs/reference/security/licensing-system.md` |
|
||||
|
||||
---
|
||||
|
||||
## Domäne A: Rechte- und Berechtigungsverwaltung
|
||||
|
||||
### StRS-001
|
||||
```
|
||||
ID: StRS-001
|
||||
Titel: Feingranulare, gruppenbasierte Rechtevergabe
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator
|
||||
Vorbedingung: Administrator ist am System mit ausreichenden Rechten angemeldet.
|
||||
Fakt: Rechte werden als benannte, nummerierte Konstanten in einer hierarchischen Struktur (UserRightsConst) gepflegt, jedes Recht ist einzeln in der Tabelle Sichrech hinterlegt und Benutzern über Gruppen zuweisbar (docs/guides/development/add-a-new-right.md, CentronRights.md).
|
||||
Aussage: Das System soll es Administratoren ermöglichen, jede geschäftskritische Funktion (Anzeigen, Anlegen, Bearbeiten, Löschen, Sonderaktionen) über ein eigenständiges, granular vergebbares Recht freizuschalten oder zu sperren.
|
||||
Ergebnis: Ein Benutzer sieht/nutzt nur die Funktionen, für die seiner Gruppe das entsprechende Recht zugewiesen wurde.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs - Begründung: Enthält >170 einzeln vergebbare Rechte-Konstanten mit fortlaufenden I3D-Werten, durchgesetzt über Datenbanktabelle Sichrech.
|
||||
- [SEKUNDÄR] CentronRights.md - Begründung: Fachliche Beschreibung einzelner Rechte in natürlicher Sprache, bestätigt Granularität am Beispiel Helpdesk (18 Einzelrechte plus Unterrechte).
|
||||
- [KONTEXT] docs/guides/development/add-a-new-right.md - Begründung: Entwicklerdokumentation beschreibt den Prozess der Rechteanlage inkl. Skript-Mechanismus, bestätigt Architekturentscheidung.
|
||||
Prüfidee: Einem Testbenutzer wird gezielt ein Einzelrecht (z. B. ADD_NEW_HELPDESK) entzogen; Ticketanlage muss verweigert werden, während andere Helpdesk-Funktionen weiter verfügbar bleiben.
|
||||
Tracelinks: SyRS-001, SyRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-002
|
||||
```
|
||||
ID: StRS-002
|
||||
Titel: Einschränkende Rechte zur Datensichtbarkeit (Eigene Daten / Eigene Filiale)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator, Fachbereichsmitarbeiter
|
||||
Vorbedingung: Benutzer besitzt ein Grundrecht (z. B. „Helpdesk anzeigen“).
|
||||
Fakt: Bestimmte Rechte sind explizit als „restricting right“ dokumentiert und schränken die Sicht-/Bearbeitungsmenge eines bereits vorhandenen Grundrechts ein (z. B. SHOW_HELPDESK_ONLY_OWN, SHOW_HELPDESK_ONLY_OWN_BRANCH, RIGHT_KALENDERANZEIGENEIGENE) (CentronRights.md).
|
||||
Aussage: Das System soll es erlauben, den Wirkungsbereich eines Grundrechts nachträglich auf „eigene Datensätze“ oder „eigene Filiale“ einzuschränken, ohne ein neues Grundrecht zu benötigen.
|
||||
Ergebnis: Benutzer mit einschränkendem Recht sehen ausschließlich die für sie relevante Teilmenge an Datensätzen (z. B. eigene Tickets, eigene Filiale).
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs Zeilen ~1959f. - Begründung: Bestätigt, dass SHOW_HELPDESK (20400295) und SHOW_HELPDESK_ONLY_OWN (20400340) als eigenständige, getrennt zuweisbare Rechte-Konstanten im durchgesetzten Rechtekatalog existieren (strukturelle Voraussetzung für unabhängige Vergabe).
|
||||
- [SEKUNDÄR] CentronRights.md (Abschnitte 1.1, 1.2, „Kalender“ Abschnitt 2) - Begründung: Beschreibt die beabsichtigte einschränkende Wirkung der Rechte in Fließtext; die tatsächliche Filterdurchsetzung selbst ist nicht Teil dieses Dokuments (siehe SyRS-002, dort als [HYPOTHESE] offen).
|
||||
Prüfidee: Zwei Benutzer derselben Gruppe, einer zusätzlich mit SHOW_HELPDESK_ONLY_OWN: Ersterer sieht alle Tickets der Filiale, Zweiterer nur eigene.
|
||||
Tracelinks: SyRS-001, SyRS-002
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne B: Belegwesen (Angebot, Auftrag, Lieferschein, Rechnung, Gutschrift)
|
||||
|
||||
### StRS-003
|
||||
```
|
||||
ID: StRS-003
|
||||
Titel: Einheitlicher Lebenszyklus für alle Belegarten
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung
|
||||
Vorbedingung: -
|
||||
Fakt: Alle Belegarten (Angebot, Auftrag, Lieferschein, Rechnung, Vertrag, Gutschrift, Abholliste) erben von derselben abstrakten Basisklasse ReceiptBase mit identischen Kernfeldern (Nummer, Datum, Version, State, Adressdaten, Audit-Felder) (ReceiptBase.cs, docs/reference/receipts/receipts-backend-architecture.md).
|
||||
Aussage: Das System soll alle Belegarten nach einem einheitlichen fachlichen Modell (Kopf/Positionen, Status, Version, Historie) abbilden, sodass Anwender über alle Belegarten hinweg dieselben Grundkonzepte (Status, Versionierung, Adressierung) wiederfinden.
|
||||
Ergebnis: Ein Beleg jeder Art besitzt konsistent Nummer, Version, Status, Ersteller/Änderer-Historie und Positionsliste.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs - Begründung: Abstrakte Klasse wird durch Quellcode-Einsicht bestätigt (Number, Date, Version, State, CreatedByI3D, ChangedByI3D, IsTemplate).
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md - Begründung: Beschreibt Tabellen-/View-Mapping je Belegart konsistent zur Entity-Struktur.
|
||||
Prüfidee: Für jede Belegart existiert eine Entity-Klasse, die von ReceiptBase erbt und ReceiptKind/GetReceiptItems() implementiert (Code-Review/Reflektion).
|
||||
Tracelinks: SyRS-003, SyRS-004
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-004
|
||||
```
|
||||
ID: StRS-004
|
||||
Titel: Nachvollziehbare Änderungshistorie je Beleg (Audit-Trail)
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional
|
||||
Akteur: Buchhaltung, IT-Administrator, Wirtschaftsprüfer [HYPOTHESE: konkreter Prüf-Akteur nicht im Code benannt, aber aus Audit-Trail-Zweck plausibel]
|
||||
Vorbedingung: Ein Beleg wird gespeichert/geändert.
|
||||
Fakt: Für jede Kopf-/Positionstabelle existiert eine korrespondierende *Versions-Tabelle als exakte 1:1-Kopie, die bei Änderungen einen Snapshot des vorherigen Zustands ablegt (docs/reference/receipts/receipts-backend-architecture.md, docs/reference/receipts/contracts-backend.md).
|
||||
Aussage: Das System soll jede Änderung an einem Beleg lückenlos versionieren, sodass frühere Zustände (Werte, Positionen) jederzeit rekonstruierbar sind.
|
||||
Ergebnis: Zu jedem Beleg existiert eine vollständige Kette historischer Versionen inklusive alter Positionsdaten.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md Abschnitt „Version Tables“ - Begründung: Beschreibt Mechanismus AssetHeadDAO.SaveAssetVersion und die 1:1-Spaltenkorrespondenz als „critical requirement“.
|
||||
- [KONTEXT] docs/reference/receipts/contracts-backend.md Abschnitt „Contract Version Creation Process“ - Begründung: Bestätigt dasselbe Muster am Beispiel VertragKopf/VertragPos, konsistente Aussage über zwei unabhängige Dokumente.
|
||||
Prüfidee: Nach Änderung eines Rechnungsfeldes existiert ein neuer Datensatz in RechKopfVersions mit dem vorherigen Wert und OriginalI3D-Referenz auf den aktuellen Datensatz.
|
||||
Tracelinks: SyRS-005, SwRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne C: Web-Angebot & digitale Signatur (C-Sign)
|
||||
|
||||
### StRS-005
|
||||
```
|
||||
ID: StRS-005
|
||||
Titel: Online-Einsicht und -Annahme von Angeboten durch den Kunden
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Kunde (Web-Login), Vertriebsmitarbeiter
|
||||
Vorbedingung: Ein Angebot wurde als Web-Angebot freigegeben und dem Kunden ein Zugriffslink (Token) mitgeteilt.
|
||||
Fakt: Die Nexus-Seite `/weboffer/{Token}` zeigt dem Kunden Positionen, Preise und Konditionen eines Angebots und bietet Buttons „Angebot annehmen“ und „Ablehnen“ (WebReceiptOverview.razor).
|
||||
Aussage: Das System soll Kunden ermöglichen, ein ihnen zugesandtes Angebot ohne Login über einen personalisierten Link einzusehen, Positionen ggf. anzupassen und final anzunehmen oder abzulehnen.
|
||||
Ergebnis: Der Kunde kann eigenständig über den Web-Zugang ein Angebot final entscheiden (annehmen/ablehnen), das System dokumentiert die Entscheidung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor Zeilen 1, 116-127, 937-987 - Begründung: Zeigt Routing per Token, Buttons und die tatsächlich aufgerufene Methode ChangeWebReceiptState mit Zustandsunterscheidung (vollständige Annahme vs. Annahme mit Änderungswünschen) sowie RejectWebReceipt.
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs - Begründung: Definiert die durchgesetzten Zustände (InProcess, AcceptFullWebReceipt, AcceptWebReceiptWithChangeRequests, Rejected, WebOfferSign, WebOfferSignedWithoutSignature) als Enum, das im Code verwendet wird.
|
||||
Prüfidee: Kunde ruft Link auf, ändert Menge einer Position, klickt „Annehmen“ → Zustand AcceptWebReceiptWithChangeRequests wird gesetzt, keine automatische Auftragsanlage ohne weiteren Schritt (siehe SyRS-006).
|
||||
Tracelinks: SyRS-006, SyRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-006
|
||||
```
|
||||
ID: StRS-006
|
||||
Titel: Rechtsverbindliche digitale Signatur bei Auftragserteilung
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Kunde (Web-Login)
|
||||
Vorbedingung: Kunde hat ein Web-Angebot vollständig angenommen; Signatur ist laut Konfiguration erforderlich (AllowAcceptReceiptWithoutSignature = false).
|
||||
Fakt: Nach Annahme wird dem Kunden ein signierbares PDF-Dokument per E-Mail-Link (`/shareddocuments/{Token}/sign`) bereitgestellt, auf dem er per Eingabe, Hochladen oder Zeichnen unterschreiben kann; erst danach wird der Auftrag final ausgelöst (ReceiptBL.AcceptWebReceipt, SharedDocumentSignPage.razor).
|
||||
Aussage: Das System soll bei aktivierter Signaturpflicht sicherstellen, dass ein Web-Angebot erst nach Erfassung einer digitalen Signatur des Kunden in einen Auftrag überführt wird.
|
||||
Ergebnis: Ein signaturpflichtiges Angebot erzeugt erst nach abgeschlossener Signatur einen Folgebeleg (Auftrag); der Vorgang und das signierte Dokument werden dem Beleg zugeordnet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6256-6309 (AcceptWebReceipt) - Begründung: Code verzweigt explizit: nur wenn AllowAcceptReceiptWithoutSignature==true wird direkt ohne Signatur fortgefahren, andernfalls wird ein SharedDocument-Signaturlink erzeugt und per Mail versendet, bevor der Beleg abgeschlossen wird.
|
||||
- [PRIMÄR] src/nexus/CentronNexus/Office/SharedDocumentSignPage.razor Zeilen 1, 84-127 - Begründung: Zeigt die tatsächliche UI zur Signaturerfassung mit drei Signaturarten (Eingeben/Hochladen/Zeichnen), bestätigt Umsetzung als eigenständige, geschützte Seite.
|
||||
Prüfidee: Bei AllowAcceptReceiptWithoutSignature=false darf ReceiptBL.AcceptWebReceipt keinen Auftrag erzeugen, bevor der Signaturvorgang abgeschlossen ist (Statuscheck WebReceiptState.WebOfferSign vor Abschluss).
|
||||
Tracelinks: SyRS-007, SyRS-008, SwRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-007
|
||||
```
|
||||
ID: StRS-007
|
||||
Titel: Konfigurierbarer Verzicht auf Signaturpflicht
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator, Vertriebsmitarbeiter
|
||||
Vorbedingung: Administrator konfiguriert Dokumenteneinstellungen eines Belegs.
|
||||
Fakt: Das Flag `AllowAcceptReceiptWithoutSignature` ist je Beleg/Dokument persistiert und wird als expliziter Codepfad ausgewertet, der die Signatur überspringt (ReceiptPdfDocument.cs, ReceiptBL.cs Zeile 6263).
|
||||
Aussage: Das System soll es erlauben, je Beleg festzulegen, ob eine Kundenannahme ohne digitale Signatur zulässig ist.
|
||||
Ergebnis: Ist das Flag gesetzt, wird der Auftrag direkt nach „Annehmen“ ohne Signaturschritt erzeugt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Administration/Documents/Receipts/ReceiptPdfDocument.cs Zeile 39 - Begründung: Bool-Property AllowAcceptReceiptWithoutSignature als persistiertes Entity-Feld.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeile 6263-6264 - Begründung: if (receiptPdfDocument.AllowAcceptReceiptWithoutSignature) return this.AcceptWebReceiptWithoutSignature(...) – direkter Verzweigungscode.
|
||||
- [SEKUNDÄR] src/backend/Centron.DAO/Mappings/Sales/Receipts/WebReceipt/ReceiptPdfDocumentMaps.cs Zeile 35 - Begründung: NHibernate-Mapping bestätigt Persistenz der Spalte.
|
||||
Prüfidee: Beleg mit AllowAcceptReceiptWithoutSignature=true: Nach Klick „Annehmen“ entsteht sofort ein Auftrag, WebReceiptState wird nicht auf WebOfferSign gesetzt.
|
||||
Tracelinks: SyRS-007, SwRS-010
|
||||
Konsolidierung: Kandidat: StRS-006 (gleiche fachliche Funktion „Auftragserteilung“, unterschiedliche Ausprägung der Signaturpflicht – im Zielsystem als ein konfigurierbarer Ablauf statt zwei Codepfade zu modellieren)
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne D: Verträge & wiederkehrende Abrechnung
|
||||
|
||||
### StRS-008
|
||||
```
|
||||
ID: StRS-008
|
||||
Titel: Abbildung wiederkehrender Serviceverträge mit automatischer Abrechnung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Buchhaltung, Vertriebsmitarbeiter
|
||||
Vorbedingung: Ein Vertrag mit Kunde, Leistungen und Abrechnungsintervall wurde angelegt.
|
||||
Fakt: ReceiptContract erweitert ReceiptBase um Abrechnungsintervall (BillingIntervalKind, BillingIntervalDuration), ein AutomatedBilling-Flag sowie eine dedizierte automatische Fakturierungslogik AutomaticFacturaBL.Contracts (docs/reference/receipts/contracts-backend.md).
|
||||
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall (täglich/monatlich/quartalsweise/jährlich) abbilden und bei aktivierter Automatik selbstständig Folgerechnungen gemäß Intervall erzeugen.
|
||||
Ergebnis: Fällige Verträge erzeugen automatisiert Rechnungen ohne manuellen Eingriff der Buchhaltung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs - Begründung: Existenz und Struktur der Entity wurde per Dateisystemsuche verifiziert (Datei vorhanden am dokumentierten Pfad).
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md - Begründung: Detailbeschreibung der Properties (BillingIntervalKind, AutomatedBilling, ContingentUsedHours etc.) und des automatisierten Ablaufs.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ContractLists/ReceiptContractBL.cs - Begründung: Datei-Existenz bestätigt, Klasse laut Doku verantwortlich für ContractContingentBalanceCalculation, UpdateDeviceToContract etc.
|
||||
Prüfidee: Vertrag mit AutomatedBilling=true und BillingIntervalKind=Monthly erzeugt nach Ablauf des Intervalls automatisch eine neue Rechnung mit korrektem Betrag.
|
||||
Tracelinks: SyRS-009, SyRS-010, SwRS-014
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-009
|
||||
```
|
||||
ID: StRS-009
|
||||
Titel: Kontingentverwaltung und -überwachung in Verträgen
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Buchhaltung, Kunde (indirekt über Servicequalität)
|
||||
Vorbedingung: Vertrag mit definiertem Kontingent (Stunden oder Betrag) existiert.
|
||||
Fakt: ReceiptContract führt separate Felder für verbrauchte Kontingentstunden/-beträge, Saldo-Verbrauch, Grenzwertüberwachung (IsContingentLimitBilling, ContingentLimitValue) und allgemeines Monitoring (IsMonitoring, MonitoringValue) (docs/reference/receipts/contracts-backend.md).
|
||||
Aussage: Das System soll den Verbrauch vertraglich vereinbarter Kontingente laufend erfassen und bei Erreichen konfigurierter Grenzwerte eine Abrechnung/Warnung auslösen können.
|
||||
Ergebnis: Kontingentüberschreitungen werden erkannt und können automatisiert zur Zusatzabrechnung führen.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md Abschnitt „Contingent Management“ / „Contingent Limits and Monitoring“ - Begründung: Beschreibt konkrete Property-Namen, die auf Basis der Namenskonvention direkt aus dem Entity ReceiptContract stammen.
|
||||
- [HYPOTHESE] Genaue Berechnungslogik/Trigger-Bedingungen für ContingentLimitKinds - Begründung zur Kennzeichnung: Die Methode ContractContingentBalanceCalculation() wurde nur über Dokumentation, nicht im Detail über Quellcode gelesen; Berechnungsformel nicht verifiziert (Analysetiefe siehe Analysebericht.md).
|
||||
Prüfidee: Vertrag mit ContingentLimitValue=100h und Verbrauch von 105h löst laut Konfiguration eine Zusatzberechnung/Benachrichtigung aus.
|
||||
Tracelinks: SyRS-010
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne E: Zeiterfassung & Timer-Billing
|
||||
|
||||
### StRS-010
|
||||
```
|
||||
ID: StRS-010
|
||||
Titel: Rechtegesteuerte Änderbarkeit des Belegdatums bei automatisierter Zeitabrechnung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierungs-/Vertriebsmitarbeiter, IT-Administrator
|
||||
Vorbedingung: Benutzer konfiguriert die Timer-Billing-Einstellungen (Assistent zur automatisierten Erstellung von Rechnungen/Lieferscheinen aus erfassten Zeiten).
|
||||
Fakt: Das Feld „Belegdatum“ im Timer-Billing-Assistenten ist nur dann bearbeitbar, wenn der Benutzer laut zentraler Einstellung CanChangeDateInInvoices (bei Rechnungen) bzw. CanChangeDateInDeliveryLists (bei Lieferscheinen) das Recht dazu besitzt; andernfalls erscheint ein Hinweistext (TimerBillingSettingsPageViewModel.cs, Commit baa9e7bd9b).
|
||||
Aussage: Das System soll die Änderbarkeit des Belegdatums beim automatisierten Timer-Billing an ein zentral konfiguriertes Recht koppeln und dem Benutzer bei fehlender Berechtigung sichtbar begründen, warum das Feld gesperrt ist.
|
||||
Ergebnis: Benutzer ohne das Recht „Datum der Rechnung/des Lieferscheins nach neuer Version / bei Neuanlage ändern“ können das Belegdatum nicht manuell setzen und erhalten eine erklärende Information.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs Methode UpdateBillingDateIsEnabled() - Begründung: Setzt BillingDateIsEnabled abhängig von CentronCache.Instance.ReceiptSettings.CanChangeDateInInvoices/CanChangeDateInDeliveryLists; direkte, durchgesetzte Rechteprüfung im UI-Datenfluss.
|
||||
- [KONTEXT] Commit baa9e7bd9b632780484edaec2330c521d39fc70b „feat: added rights check for editing invoice or delivery list date...“ - Begründung: Commit-Message bestätigt fachliche Motivation und Ticketbezug (#97) der Änderung; zeigt, dass die Regel neu eingeführt und bewusst risikogetrieben (fehlerhafte Datumsänderung) implementiert wurde.
|
||||
Prüfidee: Benutzer ohne das entsprechende Recht öffnet Timer-Billing-Assistent für Rechnungen: Feld „Belegdatum“ ist deaktiviert, Info-Icon mit Tooltip „Sie besitzen nicht das Recht ... ist sichtbar.
|
||||
Tracelinks: SyRS-011, SwRS-015, SwRS-016
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne F: Helpdesk / Ticketsystem
|
||||
|
||||
### StRS-011
|
||||
```
|
||||
ID: StRS-011
|
||||
Titel: Konfigurierbare Ticket-Status statt starrem Workflow
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator, Support-Mitarbeiter
|
||||
Vorbedingung: Administrator verwaltet Ticket-Status in den Helpdesk-Einstellungen.
|
||||
Fakt: HelpdeskState ist eine vom Anwender frei anlegbare/änderbare Entität (kein festes Enum); zwei besondere Status werden global über Anwendungseinstellungen referenziert: „geschlossen“ (HelpdeskClosedState) und „Standardstatus nach Öffnen“ (HelpdeskAfterOpenDefaultState) (HelpdeskStatusBL.cs).
|
||||
Aussage: Das System soll Administratoren erlauben, beliebig viele benannte Ticket-Status frei zu definieren, wobei genau ein Status als „geschlossen“ und einer als Standardstatus nach Wiedereröffnung ausgezeichnet werden kann.
|
||||
Ergebnis: Fachbereiche können ihren eigenen Ticket-Workflow abbilden, ohne Code-Änderungen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskStatusBL.cs Zeilen 26-50 - Begründung: GetHelpdeskStates() liefert generische Liste aus DB; GetClosedHelpdeskStatus()/GetHelpdeskAfterOpenDefaultState() lesen die referenzierte I3D aus AppSettingsBL, kein hartkodierter Statuswert im Code.
|
||||
Prüfidee: Administrator legt neuen Status „Wartet auf Kunde“ an, weist ihn keinem der beiden Sondersettings zu: Status erscheint wählbar, löst aber keine Sonderlogik (Schließen/Reopen-Default) aus.
|
||||
Tracelinks: SyRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-012
|
||||
```
|
||||
ID: StRS-012
|
||||
Titel: Schutz vor Löschung referenzierter Ticket-Status
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator
|
||||
Vorbedingung: Administrator versucht, einen Ticket-Status zu löschen, der bereits verwendet wird.
|
||||
Fakt: DeleteHelpdeskStatus() prüft vor dem Löschen die Anzahl referenzierender Tickets (HelpdeskCompact) und Task-Management-Aktionen (TaskManagementHelpdeskAction); bei mindestens einer Referenz wird eine Fehlermeldung mit Zähler zurückgegeben und der Status nicht gelöscht (HelpdeskStatusBL.cs Zeilen 75-104).
|
||||
Aussage: Das System soll das Löschen eines Ticket-Status verhindern, solange dieser noch von mindestens einem Ticket oder einer Task-Aktion referenziert wird, und den Grund (Anzahl betroffener Datensätze) benennen.
|
||||
Ergebnis: Referenzielle Integrität der Ticket-Historie bleibt erhalten; der Administrator erhält eine konkrete, deutschsprachige Fehlermeldung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskStatusBL.cs Zeilen 75-104 - Begründung: Vollständiger Methodencode mit Zählabfrage und bedingter Result.AsError-Rückgabe wurde eingesehen; harte, durchgesetzte Regel.
|
||||
Prüfidee: Löschversuch eines Status, der auf 3 Tickets und 1 Task verwendet wird, liefert Fehlermeldung „... wird in 3 Tickets & 1 Task verwendet.“ und der Datensatz bleibt bestehen.
|
||||
Tracelinks: SyRS-012, SwRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne G: Lieferanten-Datenaustausch (EDI)
|
||||
|
||||
### StRS-013
|
||||
```
|
||||
ID: StRS-013
|
||||
Titel: Automatisierte Verarbeitung strukturierter Lieferantendokumente
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Einkauf/Wareneingang, externes Lieferantensystem
|
||||
Vorbedingung: Für einen Lieferanten ist eine EDI-Konfiguration (Format, Verbindungsdaten) hinterlegt.
|
||||
Fakt: SupplierEdiBL (mit Partial-Klassen je Lieferant: Also, AlsoCH, Alltron, Herweck, Komsa, Opentrans) verarbeitet über die zentrale Methode ApplyDistriToCentron(...) Auftragsbestätigungen, Lieferungen und Rechnungen unterschiedlicher Lieferantenformate in c-entron-Belege (SupplierEdiBL.cs Zeile 1364, docs/reference/edi/edi-architecture.md).
|
||||
Aussage: Das System soll eingehende, lieferantenspezifisch formatierte EDI-Dokumente (Auftragsbestätigung, Lieferung, Rechnung) automatisiert einlesen, auf bestehende Aufträge abgleichen und als c-entron-Belege weiterverarbeiten.
|
||||
Ergebnis: Manuelle Ersterfassung von Lieferanten-Belegen entfällt für angebundene Lieferanten weitgehend.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs Zeile 1364 - Begründung: Signatur der zentralen Dispatch-Methode ApplyDistriToCentron(List<EDIDistriFile>, SupplierEdiConfigurations, OrderInfo) wurde im Quellcode verifiziert.
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md - Begründung: Beschreibt Format-/Dokumenttyp-Matrix (OpenTrans, ALSO, ALSO CH, Herweck, Komsa, Alltron, ZUGFeRD) und Partial-Class-Architektur konsistent zu den vorgefundenen Dateinamen (SupplierEdiBL.Also.cs, .AlsoCH.cs, .Alltron.cs, .Herweck.cs, .Komsa.cs, .Opentrans.cs).
|
||||
Prüfidee: Import einer ALSO-CH-Auftragsbestätigungsdatei führt zu aktualisiertem Auftragsstatus im referenzierten c-entron-Auftrag ohne manuellen Eingriff.
|
||||
Tracelinks: SyRS-013, SyRS-014
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-014
|
||||
```
|
||||
ID: StRS-014
|
||||
Titel: Nicht jeder Lieferant unterstützt jeden Dokumenttyp
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Einkauf
|
||||
Vorbedingung: -
|
||||
Fakt: Laut Dokumentation unterstützt der Lieferant „Komsa“ Auftragsbestätigung und Lieferung, jedoch keine elektronische Rechnung (✗ in der Matrix), während „ZUGFeRD“ ausschließlich Rechnungen abdeckt (edi-architecture.md Tabelle „Document Types Supported“).
|
||||
Aussage: Das System soll pro Lieferant/Format nur die tatsächlich unterstützten Dokumenttypen zur Verarbeitung anbieten bzw. für nicht unterstützte Kombinationen keine automatisierte Verarbeitung vortäuschen.
|
||||
Ergebnis: Lieferantenrechnungen von Komsa werden weiterhin manuell erfasst; keine fehlerhaften Automatik-Erwartungen der Fachanwender.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md Tabelle „Document Types Supported“ - Begründung: Explizite Dokumentation der Formatabdeckung; nicht am Code selbst verifiziert (kein direkter Blick in SupplierEdiBL.Komsa.cs), daher SEKUNDÄR statt PRIMÄR.
|
||||
- [HYPOTHESE] Ob SupplierEdiBL.Komsa.cs tatsächlich keine ReadKomsaInvoice-Methode enthält - Begründung zur Kennzeichnung: nicht im Rahmen dieser Iteration im Code verifiziert; zur Bestätigung wäre ein direkter Dateivergleich nötig (siehe Analysebericht.md, Bereich EDI: stichprobenhaft).
|
||||
Prüfidee: Code-Inspektion von SupplierEdiBL.Komsa.cs bestätigt Fehlen einer Invoice-Verarbeitungsmethode.
|
||||
Tracelinks: SyRS-013
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne H: Authentifizierung & Lizenzierung
|
||||
|
||||
### StRS-015
|
||||
```
|
||||
ID: StRS-015
|
||||
Titel: Alternative Anmeldung über unternehmensweite Microsoft-Identität (SSO)
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Endbenutzer (Mitarbeiter), Microsoft Entra ID
|
||||
Vorbedingung: Der Kunde besitzt die Lizenz „OpenIDConnectAuthentication“ und hat OIDC serverseitig konfiguriert (JwtAuthority/JwtAudience).
|
||||
Fakt: Ein Benutzer kann sich statt mit internem Passwort über seine Microsoft-Entra-Identität anmelden; das System tauscht ein Microsoft-ID-Token gegen ein internes, zeitlich befristetes c-entron-Ticket (OpenIdConnectAuthenticator.cs, TicketBL.cs, docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md).
|
||||
Aussage: Das System soll Single-Sign-On über Microsoft Entra ID als alternative, lizenzpflichtige Anmeldemethode zum internen Passwort-Login anbieten.
|
||||
Ergebnis: Berechtigte Kunden können sich ohne separates c-entron-Passwort anmelden; Zuordnung erfolgt eindeutig über die Microsoft Object-ID des Benutzers.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/OpenIdConnectAuthenticator.cs - Begründung: Vollständiger Methodencode (AuthenticateInternal) zeigt Lizenzprüfung (LicenseGuids.OpenIDConnectAuthentication), Claim-Validierung und DB-Lookup über OpenIdConnectSubjectIdentifier.
|
||||
- [SEKUNDÄR] docs/reference/security/anmelden-mit-microsoft-technische-anleitung.md - Begründung: Detaillierte, mit Dateipfaden belegte Ablaufbeschreibung; ergänzt, aber ersetzt nicht die Primärverifikation im Code.
|
||||
Prüfidee: Benutzer ohne Lizenz OpenIDConnectAuthentication erhält bei OIDC-Login-Versuch den Fehler „No license for OpenIDConnectAuthentication“, unabhängig von einem gültigen Microsoft-Token.
|
||||
Tracelinks: SyRS-015, SyRS-016, SwRS-020, SwRS-021
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### StRS-016
|
||||
```
|
||||
ID: StRS-016
|
||||
Titel: Feature- und mengenbasierte Lizenzierung einzelner Funktionen
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: IT-Administrator, Betreiber/Lizenzserver
|
||||
Vorbedingung: -
|
||||
Fakt: Lizenzen werden als GUIDs mit optionalem Zähler, Ablaufdatum und Versionsgrenze modelliert; LicenseManager bietet HasLicense(Guid) und GetLicenseCount(Guid) zur Laufzeitprüfung (LicenseManager.cs Zeilen 243, 332; docs/reference/security/licensing-system.md).
|
||||
Aussage: Das System soll einzelne Funktionen (Module, Add-Ins, Mengenkontingente wie Importe) unabhängig voneinander per Lizenz freischalten und dabei sowohl das reine Vorhandensein als auch eine Mengenbeschränkung prüfen können.
|
||||
Ergebnis: Nicht lizenzierte Funktionen bleiben für den Kunden unsichtbar/inaktiv; mengenbeschränkte Funktionen (z. B. Anzahl Importe) werden serverseitig durchgesetzt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs Zeilen 243, 332 - Begründung: Methodensignaturen HasLicense(Guid) und GetLicenseCount(Guid) im Quellcode verifiziert.
|
||||
- [SEKUNDÄR] docs/reference/security/licensing-system.md - Begründung: Erklärt fachliches Modell (Applications vs. Only Licenses, count/valid until date/valid until version) mit Codebeispielen, die zu den verifizierten Methoden passen.
|
||||
Prüfidee: LicenseManager.Instance.HasLicense(LicenseGuids.PasswordManager) liefert false für einen Kunden ohne diese Lizenz, UI-Modul „Passwort-Manager“ wird nicht angezeigt.
|
||||
Tracelinks: SyRS-015, SyRS-017
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne I: Bedienbarkeit der WPF-Oberfläche
|
||||
|
||||
### StRS-017
|
||||
```
|
||||
ID: StRS-017
|
||||
Titel: Erkennbarkeit des aktiven Moduls auch bei minimiertem Ribbon
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional
|
||||
Akteur: Alle internen Benutzer der WPF-Anwendung
|
||||
Vorbedingung: Benutzer hat das Ribbon (Hauptnavigation) minimiert.
|
||||
Fakt: Vor Commit 8dd17c7d12 blendete DevExpress bei minimiertem Ribbon den Indikator für die aktive Seite/das aktive Modul aus; der Fix zeichnet manuell eine Unterstreichung der Caption, wenn die Seite ausgewählt und das Ribbon minimiert ist (Commit-Message 8dd17c7d1244c02ef57ee3f94a42249a056c74cd, Ticket 150766).
|
||||
Aussage: Das System soll dem Benutzer jederzeit – auch bei minimiertem Ribbon – visuell eindeutig anzeigen, welches Modul/welcher Tab aktuell aktiv ist.
|
||||
Ergebnis: Benutzer können ohne Ribbon-Expansion erkennen, in welchem Modul sie sich befinden.
|
||||
Belege:
|
||||
- [KONTEXT] Commit 8dd17c7d1244c02ef57ee3f94a42249a056c74cd „Ticket 150766: Fix missing active tab indicator when ribbon is minimized“ - Begründung: Commit-Message beschreibt exakt Ursache (DevExpress verhalten) und Lösung (manuelles Underline-Rendering); Ticketreferenz belegt, dass dies ein realer, von Endanwendern gemeldeter Mangel war.
|
||||
- [SEKUNDÄR] src/centron/Centron.WPF.UI/Classes/Modules/ModuleResources.xaml (laut Diff-Stat 79 geänderte Zeilen) - Begründung: Betroffene Ressourcendatei wurde nicht im Volltext gelesen, Änderungsumfang nur über `git show --stat` bestätigt.
|
||||
Prüfidee: Ribbon minimieren, Modul wechseln: aktiver Tab zeigt sichtbare Unterstreichung/Hervorhebung ohne Ribbon-Expansion.
|
||||
Tracelinks: SyRS-018, SwRS-024
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Ende StRS. Fortsetzung der Verfeinerung in [SyRS.md](SyRS.md) und [SwRS.md](SwRS.md). Gesamtübersicht in [Traceability.md](Traceability.md).*
|
||||
+504
@@ -0,0 +1,504 @@
|
||||
# Software Requirements Specification (SwRS)
|
||||
|
||||
Komponenten-, Datenmodell- und softwareinterne Regeln gemäß ISO/IEC/IEEE 29148:2018, verfeinert aus [SyRS.md](SyRS.md). Diese Ebene benennt konkrete Klassen, Methoden, Felder und Enums.
|
||||
|
||||
---
|
||||
|
||||
## Domäne A: Rechte- und Berechtigungsverwaltung
|
||||
|
||||
### SwRS-001
|
||||
```
|
||||
ID: SwRS-001
|
||||
Titel: Rechtekonstanten als hierarchisch verschachtelte, versionsstabile Ganzzahlen
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Entwickler, System
|
||||
Vorbedingung: -
|
||||
Fakt: UserRightsConst.cs organisiert Rechte in verschachtelten statischen Klassen nach Modulhierarchie (z. B. UserRightsConst.Sales.Customer.Helpdesk.SHOW_HELPDESK) mit einem Kopfkommentar, der den nächsten freien I3D-Wert festhält („NEW .NET MODULE RIGHTS START AT 20800000, NEXT ID: 20800174“).
|
||||
Aussage: Die Software soll Rechte-IDs als unveränderliche, fortlaufend vergebene Ganzzahlkonstanten in einer nach Fachmodulen verschachtelten Klassenhierarchie definieren, wobei bestehende Werte nach Vergabe nicht wiederverwendet werden dürfen.
|
||||
Ergebnis: Neue Rechte erhalten eindeutige, nie zuvor vergebene IDs; die Kommentarzeile dient als manuelles Register des nächsten freien Werts.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs Zeilen 1-20 - Begründung: Kopfkommentar und Namespace-/Klassenstruktur wörtlich eingesehen.
|
||||
Prüfidee: Statische Code-Analyse: keine zwei Konstanten in UserRightsConst.cs besitzen denselben Integer-Wert.
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (manuelle statt automatisierte ID-Vergabe, Fehlerquelle bei parallelen Merges)
|
||||
```
|
||||
|
||||
### SwRS-002
|
||||
```
|
||||
ID: SwRS-002
|
||||
Titel: Veraltete Rechte bleiben aus Kompatibilitätsgründen erhalten
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Entwickler
|
||||
Vorbedingung: -
|
||||
Fakt: Mehrere Konstanten sind explizit mit `[Obsolete]` markiert (z. B. LOGGED_IN_USER_VIEW=10130, TAPI_SUPPORT=20400070, ACCOUNTING_BOOK_EXTENDED_VIEW=20400087, SHOW_MARKET_BASKET=20400182), bleiben aber im Quellcode und vermutlich in der Datenbank bestehen.
|
||||
Aussage: Die Software soll nicht mehr verwendete Rechte durch das `[Obsolete]`-Attribut kennzeichnen, anstatt sie zu löschen, um Rückwärtskompatibilität mit bestehenden Datenbank-Rechtezuweisungen (Sichrech) zu wahren.
|
||||
Ergebnis: Alte Gruppen-/Benutzerzuordnungen zu obsoleten Rechten verursachen keinen Fehler, werden aber vom Compiler als Warnung markiert, wenn sie im Code neu referenziert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs Zeilen 21-28 - Begründung: Vier konkrete [Obsolete]-Konstanten mit Werten im Quellcode eingesehen.
|
||||
Prüfidee: Neue Codeverwendung einer obsoleten Konstante erzeugt eine Compiler-Warnung (CS0618), verhindert den Build aber nicht.
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
### SwRS-003
|
||||
```
|
||||
ID: SwRS-003
|
||||
Titel: Redundante Rechteprüfung auf UI- und BL-Ebene
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Entwickler
|
||||
Vorbedingung: -
|
||||
Fakt: Es existieren mindestens drei dokumentierte, unterschiedliche Prüfpfade für dasselbe fachliche Recht: `CentronCache.Instance.CurrentUserAppRights.Any(...)` (ViewModel), `Helper.HasRights(...)` (Modulregistrierung) und `AppRightsBL.CheckRightsFromUser(...)` (BL) (docs/guides/development/check-userrights.md).
|
||||
Aussage: Die Software verwendet für dieselbe fachliche Rechteprüfung je nach Schicht unterschiedliche technische Mechanismen, die alle auf denselben zugrunde liegenden Rechtewert zugreifen, aber unabhängig gepflegt/aufgerufen werden müssen.
|
||||
Ergebnis: Ein Entwickler muss die Rechteprüfung ggf. an mehreren Stellen (UI-Sichtbarkeit UND BL-Durchsetzung) separat implementieren.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/guides/development/check-userrights.md - Begründung: Dokumentiert alle drei Zugriffsmuster nebeneinander als jeweils „richtige“ Vorgehensweise je Schicht, ohne dies als Redundanz zu benennen; Einstufung als Konsolidierungskandidat ist eigene fachliche Interpretation dieser Analyse.
|
||||
Prüfidee: Code-Review: Für ein Beispielrecht wird geprüft, ob UI-Sichtbarkeitsprüfung und BL-Durchsetzungsprüfung unabhängig voneinander gepflegt werden (z. B. unterschiedliche Rechte-ID durch Copy-Paste-Fehler).
|
||||
Tracelinks: SyRS-001
|
||||
Konsolidierung: Kandidat: Vereinheitlichung der Rechteprüfung auf einen einzigen, schichtübergreifend wiederverwendbaren Mechanismus im Zielsystem (z. B. Policy-based Authorization statt drei paralleler APIs).
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne B: Belegwesen
|
||||
|
||||
### SwRS-004
|
||||
```
|
||||
ID: SwRS-004
|
||||
Titel: ReceiptBase als abstrakte Basisklasse mit Template-Kennzeichnung über Vorzeichen
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `public virtual bool IsTemplate => Number < 0;` – die Eigenschaft „ist Vorlage“ wird nicht über ein eigenes Flag, sondern über das Vorzeichen der Belegnummer abgeleitet (ReceiptBase.cs Zeile 65).
|
||||
Aussage: Die Software soll einen Beleg genau dann als Vorlage (Template) behandeln, wenn seine Belegnummer negativ ist; positive und Null-Nummern gelten als reguläre Belege.
|
||||
Ergebnis: Es existiert kein separates Datenbankfeld für „ist Vorlage“; die Semantik ist vollständig aus der Nummer ableitbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs Zeile 65 - Begründung: Wörtliches Zitat der Implementierung.
|
||||
Prüfidee: Ein Beleg mit Number=-1 liefert IsTemplate=true; ein Beleg mit Number=0 oder positiv liefert IsTemplate=false.
|
||||
Tracelinks: StRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (implizite Kodierung einer Fachbedeutung über das Vorzeichen eines numerischen Feldes – Risiko: neue Entwickler könnten negative Nummern versehentlich als Fehler interpretieren)
|
||||
```
|
||||
|
||||
### SwRS-005
|
||||
```
|
||||
ID: SwRS-005
|
||||
Titel: Belegstatus als geschlossenes Drei-Werte-Enum
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `ReceiptState` kennt exakt drei Werte: Active (1, "offen"), Completed (2, "abgeschlossen"), Canceled (3, "storniert") (ReceiptState.cs).
|
||||
Aussage: Die Software soll für den Grundstatus eines Belegs (unabhängig vom spezifischeren WebReceiptState eines Web-Angebots) genau die drei Zustände offen/abgeschlossen/storniert unterscheiden.
|
||||
Ergebnis: Jeder Beleg jeder Art besitzt zu jedem Zeitpunkt genau einen dieser drei Werte.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Vollständiges Enum mit deutschen Description-Attributen im Quellcode eingesehen.
|
||||
Prüfidee: Für jeden Belegtyp lässt sich per Unit-Test verifizieren, dass State nur einen der drei Enum-Werte annehmen kann (Datenbankkonsistenzprüfung).
|
||||
Tracelinks: StRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne C: Web-Angebot & digitale Signatur (C-Sign)
|
||||
|
||||
### SwRS-006
|
||||
```
|
||||
ID: SwRS-006
|
||||
Titel: WebReceiptState als erweitertes Zustandsmodell für den Web-Kanal
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `WebReceiptState` (DataContract-Enum) definiert neun Werte: InProcess, AcceptFullWebReceipt, AcceptWebReceiptWithChangeRequests, Rejected, SendToCustomer, FirstLoaded, WebOfferSign, WebReceiptShutDown, WebOfferSignedWithoutSignature (WebReceiptState.cs).
|
||||
Aussage: Die Software soll den Lebenszyklus eines Web-Angebots über ein eigenständiges, feingranulareres Zustandsmodell abbilden, das zwischen „voll angenommen“, „mit Änderungswünschen angenommen“, „zur Signatur“ und „ohne Signatur akzeptiert“ unterscheidet.
|
||||
Ergebnis: Der Beleg-Grundstatus (ReceiptState) und der Web-Angebots-Status (WebReceiptState) werden parallel, aber unabhängig voneinander geführt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs - Begründung: Vollständiges Enum mit [DataContract]/[EnumMember]-Attributen (WCF/REST-Serialisierung) im Quellcode eingesehen.
|
||||
Prüfidee: Ein Web-Angebot im Zustand WebOfferSign hat gleichzeitig ReceiptState.Active, bis die Signatur abgeschlossen ist.
|
||||
Tracelinks: SyRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-007
|
||||
```
|
||||
ID: SwRS-007
|
||||
Titel: Change-Request-Persistenz statt sofortiger Belegänderung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (WebReceiptItemChangeRequest)
|
||||
Vorbedingung: Kunde ändert im Web-Angebot Menge oder Positionsart einer Zeile.
|
||||
Fakt: Änderungen werden nicht direkt am Originalbeleg vorgenommen, sondern als `WebReceiptItemChangeRequest`-Datensatz mit `ChangeRequestKind` (u. a. QuantityChange, ReceiptItemArticlePositionKindChange) gespeichert, die aufrufende Methode ist `CentronService.RequestForWebReceiptItemChange(Token, kind, receiptItemI3D, newQuantity, newKind)` (WebReceiptOverview.razor Zeilen 836, 874, 882, 1142, 1158; ChangeRequestKind.cs).
|
||||
Aussage: Die Software soll vom Kunden im Web-Angebot vorgenommene Änderungen zunächst als eigenständige, änderbare Change-Request-Datensätze festhalten und erst bei Annahme (ChangeWebReceiptState) in eine neue Belegversion überführen.
|
||||
Ergebnis: Der Originalbeleg bleibt bis zur formellen Annahme unverändert; mehrere Änderungen derselben Position werden über ChangeDate dedupliziert (jeweils die letzte gewinnt, siehe ReceiptBL.cs Zeilen 6209-6212 `GroupBy(...).OrderByDescending(x => x.ChangeDate).Select(f => f.First())`).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6202-6243 (AcceptWebReceiptChanges) - Begründung: Vollständiger Methodencode zeigt Gruppierung nach (ReceiptItemI3D, ChangeRequestKind), Auswahl der jüngsten Änderung und deren Anwendung auf eine neue Belegversion.
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor Zeilen 808-863 (OnQuantityChange) - Begründung: Zeigt clientseitige Erzeugung der Change-Request statt direkter Beleg-Manipulation.
|
||||
Prüfidee: Kunde ändert dieselbe Position zweimal (Menge 5 dann 3): Nach Annahme wird nur die letzte Änderung (3) im neuen Beleg übernommen.
|
||||
Tracelinks: StRS-005, SyRS-007
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-008
|
||||
```
|
||||
ID: SwRS-008
|
||||
Titel: Rechtekombination steuert erlaubte Änderungsarten je Beleg (AllowChangeQuantity, AllowChangeReceiptItemArticlePositionKind)
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptPdfDocument)
|
||||
Vorbedingung: Web-Angebot wird angenommen und enthält Change-Requests.
|
||||
Fakt: `AcceptWebReceiptChanges` wendet eine Mengenänderung nur an, wenn `receiptPdfDocument.AllowChangeQuantity` wahr ist, und eine Positionsart-Änderung nur, wenn `AllowChangeReceiptItemArticlePositionKind` wahr ist; ist das Flag falsch, wird die betreffende Change-Request stillschweigend übersprungen (`break` ohne Anwendung) (ReceiptBL.cs Zeilen 6229-6239).
|
||||
Aussage: Die Software soll bei der Übernahme von Kundenänderungen jede Änderungsart individuell gegen ein je-Beleg konfiguriertes Erlaubnis-Flag prüfen und nicht erlaubte Änderungsarten kommentarlos verwerfen.
|
||||
Ergebnis: Ein Administrator kann z. B. Mengenänderungen erlauben, aber Änderungen der Positionsart (Alternative/Optional/...) sperren, oder umgekehrt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6226-6242 - Begründung: switch-Statement mit expliziten if(...==false) break-Zweigen pro ChangeRequestKind wörtlich eingesehen.
|
||||
Prüfidee: Beleg mit AllowChangeQuantity=false, AllowChangeReceiptItemArticlePositionKind=true: Nach Annahme wird nur die Positionsart-Änderung übernommen, eine vom Kunden vorgenommene Mengenänderung wird verworfen (potenziell ohne Information an den Kunden – siehe Hypothesen.md).
|
||||
Tracelinks: StRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-009
|
||||
```
|
||||
ID: SwRS-009
|
||||
Titel: Fehlschlag bei fehlenden Change-Requests trotz erfolgter Annahme
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: AcceptWebReceiptChanges wird aufgerufen.
|
||||
Fakt: Wenn keine Change-Request-Datensätze zum Beleg gefunden werden, wirft die Methode eine generische `Exception("Receipt change item requests was not found in Database")` (ReceiptBL.cs Zeilen 6204-6207).
|
||||
Aussage: Die Software soll den Annahmevorgang mit Änderungswünschen abbrechen, wenn zum Zeitpunkt der Verarbeitung keine zugehörigen Change-Request-Datensätze mehr vorliegen.
|
||||
Ergebnis: Ein Zustand „Annahme mit Änderungswünschen“ ohne persistierte Änderungswünsche führt zu einem Serverfehler statt zu einer stillen Vollannahme.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6202-6207 - Begründung: Wörtlicher Code der Prüfung und Exception.
|
||||
Prüfidee: Race-Condition-Test: Change-Requests werden zwischen Klick „Annehmen“ und Serververarbeitung durch einen parallelen Prozess gelöscht → Server antwortet mit Fehler statt fälschlicher Vollannahme.
|
||||
Tracelinks: StRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (generische Exception statt strukturierter Fehlerrückgabe/Result-Pattern, inkonsistent zum sonst verwendeten Result<T>-Muster laut docs/reference/architecture/results-and-responses.md)
|
||||
```
|
||||
|
||||
### SwRS-010
|
||||
```
|
||||
ID: SwRS-010
|
||||
Titel: Signaturpfad erzeugt zwei getrennte Benachrichtigungsmails (Kunde/Mitarbeiter)
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (MailTemplateBL)
|
||||
Vorbedingung: AcceptWebReceipt mit Signaturpflicht wird ausgeführt.
|
||||
Fakt: Es werden zwei unterschiedliche, fest referenzierte Mail-Templates geladen und versendet: `MailTemplateReferences.WebOffer.AcceptWebOfferToSignCustomer` an den Kunden und `...AcceptWebOfferToSignEmployee` an den zuständigen Mitarbeiter, mit einer generierten Signatur-URL `{centronNexusURL}/shareddocuments/{Token}/sign` (ReceiptBL.cs Zeilen 6290-6300).
|
||||
Aussage: Die Software soll bei Auslösung des Signaturvorgangs sowohl den Kunden (mit Signaturlink) als auch den zuständigen internen Mitarbeiter (zur Information) automatisiert per E-Mail benachrichtigen.
|
||||
Ergebnis: Beide Parteien sind informiert; der Mitarbeiter kann den offenen Signaturvorgang nachverfolgen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6290-6300 - Begründung: Wörtlicher Code mit zwei separaten SendMailForWebReceipt-Aufrufen und unterschiedlichen Empfängerlisten.
|
||||
Prüfidee: Nach Auslösung des Signaturvorgangs erhält sowohl die Kunden-E-Mail-Adresse (receiptPdfDocument.MailAddress) als auch die Mitarbeiter-E-Mail-Adresse je eine E-Mail mit unterschiedlichem Template.
|
||||
Tracelinks: StRS-006, SyRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-011
|
||||
```
|
||||
ID: SwRS-011
|
||||
Titel: Zeitlich befristeter Signatur-Token mit konfigurierbarer Gültigkeitsdauer
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (SharedDocumentBL)
|
||||
Vorbedingung: Signaturvorgang wird ausgelöst.
|
||||
Fakt: `GenerateTokenForDocument(...)` erhält als Ablaufdatum entweder `null` (kein Ablauf) oder `DateTime.Now.AddDays(settings.OfferSignExpiredDateCount.Value)`, abhängig von einer administrativ konfigurierbaren Tageszahl `OfferSignExpiredDateCount` (ReceiptBL.cs Zeile 6287).
|
||||
Aussage: Die Software soll die Gültigkeitsdauer eines Signatur-Links administrativ in Tagen konfigurierbar machen und optional ein unbefristetes Ablaufverhalten zulassen, wenn kein Wert gesetzt ist.
|
||||
Ergebnis: Nicht rechtzeitig signierte Angebote können nach Ablauf nicht mehr über denselben Link abgeschlossen werden (sofern konfiguriert).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeile 6287 - Begründung: Wörtlicher Ausdruck `settings.OfferSignExpiredDateCount is null ? null : DateTime.Now.AddDays(...)`.
|
||||
- [HYPOTHESE] Verhalten bei abgelaufenem Token (Fehlermeldung, erneute Anforderung möglich?) - Begründung zur Kennzeichnung: SharedDocumentSignPage.razor zeigt zwar eine generische Meldung „Ungültiger Link“ (Zeile 30-38 der Datei), es wurde aber nicht verifiziert, ob dieselbe Meldung auch für „abgelaufen“ (im Unterschied zu „nie existiert“) verwendet wird.
|
||||
Prüfidee: OfferSignExpiredDateCount=7: Link ist am Tag 7 nutzbar, am Tag 8 liefert der Aufruf „Ungültiger Link“.
|
||||
Tracelinks: StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
### SwRS-012
|
||||
```
|
||||
ID: SwRS-012
|
||||
Titel: Drei gleichwertige Erfassungsarten für die digitale Signatur
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Kunde
|
||||
Vorbedingung: Kunde befindet sich auf der Signaturseite.
|
||||
Fakt: `SignatureType` unterscheidet mindestens Type (getippter Name in wählbarer Schriftart Georgia/Arial/Monaco/Brush Script MT und Farbe Schwarz/Blau/Lila), Upload (Datei-Upload) und Draw (freihändiges Zeichnen) (SharedDocumentSignPage.razor Zeilen 87-127).
|
||||
Aussage: Die Software soll dem Kunden zur Signaturerfassung wahlweise das Eingeben eines Namens in einer Signaturschriftart, das Hochladen einer vorhandenen Unterschrift oder das freihändige Zeichnen anbieten.
|
||||
Ergebnis: Der Kunde wählt eine der drei gleichwertigen Erfassungsmethoden; das Ergebnis wird in das PDF-Dokument eingebettet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/Office/SharedDocumentSignPage.razor Zeilen 84-127 - Begründung: Drei UI-Optionen (Eingeben/Hochladen/Zeichnen) mit zugehörigen Steuerelementen wörtlich im Markup eingesehen.
|
||||
Prüfidee: Für jede der drei SignatureType-Varianten entsteht ein gültiges, im PDF sichtbares Signaturbild.
|
||||
Tracelinks: StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne D: Verträge
|
||||
|
||||
### SwRS-013
|
||||
```
|
||||
ID: SwRS-013
|
||||
Titel: ReceiptContract erweitert ReceiptBase um vertragsspezifische Felder
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: Laut Dokumentation (contracts-backend.md) implementiert `ReceiptContract` zusätzlich zu den Basisfeldern u. a. `BillingIntervalKind`, `BillingIntervalDuration`, `BillingKind`, `AutomatedBilling`, `CalculationKind`, `PaymentConditionI3D`, `MandatI3D` (SEPA-Mandat); Datei-Existenz am dokumentierten Pfad wurde verifiziert.
|
||||
Aussage: Die Software soll Verträge als eigenständige Entity-Klasse abbilden, die von der gemeinsamen Beleg-Basis erbt und ausschließlich vertragsspezifische Zusatzfelder (Abrechnung, Kontingent, SEPA) ergänzt.
|
||||
Ergebnis: Verträge nutzen dieselbe Beleginfrastruktur (Versionierung, Audit, Adressierung) wie andere Belegarten.
|
||||
Belege:
|
||||
- [PRIMÄR] Datei-Existenz src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs - Begründung: Pfad wurde per Dateisystemsuche bestätigt.
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md Abschnitt „Core Contract Properties“ - Begründung: Feldliste wurde nicht durch Öffnen der Datei selbst verifiziert (Analysetiefe: Kontrakt-Domäne stichprobenhaft, siehe Analysebericht.md).
|
||||
Prüfidee: Reflection-Test: ReceiptContract.BaseType == typeof(ReceiptBase); Properties enthalten BillingIntervalKind und MandatI3D.
|
||||
Tracelinks: StRS-008
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-014
|
||||
```
|
||||
ID: SwRS-014
|
||||
Titel: SEPA-Mandatsreferenz als optionales Vertragsfeld
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Buchhaltung
|
||||
Vorbedingung: Vertrag nutzt Lastschrifteinzug.
|
||||
Fakt: `MandatI3D` referenziert laut Dokumentation ein SEPA-Mandat innerhalb der Zahlungs-/Inkasso-Konfiguration eines Vertrags (contracts-backend.md Abschnitt „Payment and Collection“).
|
||||
Aussage: Die Software soll einem Vertrag optional ein SEPA-Mandat zuordnen können, um automatisierten Lastschrifteinzug für daraus resultierende Rechnungen zu ermöglichen.
|
||||
Ergebnis: Rechnungen aus Verträgen mit hinterlegtem Mandat können dem SEPA-Lastschriftverfahren zugeführt werden.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md Abschnitt „Payment and Collection“ - Begründung: Nur Feldname und grobe Bedeutung dokumentiert, keine Codeeinsicht in dieser Iteration; als [HYPOTHESE] eingestuft, da SEPA-Verarbeitungslogik selbst nicht verifiziert wurde.
|
||||
- [HYPOTHESE] Tatsächliche SEPA-Exportlogik (z. B. XML-Erzeugung, Fristenprüfung) - Begründung zur Kennzeichnung: nicht Teil der in dieser Iteration gelesenen Dateien.
|
||||
Prüfidee: Rechnung aus Vertrag mit MandatI3D erzeugt einen SEPA-Lastschrift-Exportdatensatz mit korrekter Mandatsreferenz.
|
||||
Tracelinks: StRS-008
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne E: Zeiterfassung & Timer-Billing
|
||||
|
||||
### SwRS-015
|
||||
```
|
||||
ID: SwRS-015
|
||||
Titel: BillingDateIsEnabled als abgeleiteter, nicht persistierter UI-Zustand
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (TimerBillingSettingsPageViewModel)
|
||||
Vorbedingung: Benutzer wählt ReceiptKind (Rechnung/Lieferschein) oder UseBillingDate im Assistenten.
|
||||
Fakt: `UpdateBillingDateIsEnabled()` wird als Seiteneffekt der Setter von `ReceiptKind` und `UseBillingDate` aufgerufen (nicht bei jedem Rendern neu berechnet) und setzt `BillingDateIsEnabled`, `ShowBillingDateNoteEnabledInfo` sowie den Hinweistext `BillingDateNotEnabledInfo` abhängig vom gewählten ReceiptKind (TimerBillingSettingsPageViewModel.cs Zeilen 195-247, 563-586).
|
||||
Aussage: Die Software soll bei jeder Änderung von Belegart oder „Belegdatum verwenden“ im Timer-Billing-Assistenten unmittelbar neu bewerten, ob das Belegdatum-Feld bearbeitbar ist, und bei Sperrung einen belegartspezifischen Erklärungstext („der Rechnung“ / „des Lieferscheins“) anzeigen.
|
||||
Ergebnis: Der Benutzer erhält sofort nach Auswahl der Belegart eine konsistente, kontextabhängige Rückmeldung, ohne die Seite neu laden zu müssen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs (Diff aus Commit baa9e7bd9b, Zeilen ~195-247, 563-586) - Begründung: Vollständiger Methodencode inkl. bedingtem Textbaustein `$"Sie besitzen nicht das Recht \"Datum {receiptKindPart} nach neuer Version / bei Neuanlage ändern\"."` wörtlich im Commit-Diff eingesehen.
|
||||
Prüfidee: Wechsel von ReceiptKind=InvoiceClass zu DeliveryList bei fehlendem Recht: Hinweistext wechselt von „der Rechnung“ zu „des Lieferscheins“ ohne Seiten-Reload.
|
||||
Tracelinks: StRS-010, SyRS-011
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-016
|
||||
```
|
||||
ID: SwRS-016
|
||||
Titel: UseBillingDate als übergeordnete Vorbedingung für BillingDateIsEnabled
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `UpdateBillingDateIsEnabled()` setzt `BillingDateIsEnabled=false` und `ShowBillingDateNoteEnabledInfo=false` sofort, wenn `UseBillingDate=false` ist, unabhängig vom Rechtestatus; die Rechteprüfung greift erst, wenn `UseBillingDate=true` ist.
|
||||
Aussage: Die Software soll den Hinweis auf ein fehlendes Recht nur dann anzeigen, wenn die Funktion „Belegdatum verwenden“ überhaupt aktiviert ist; bei deaktivierter Funktion soll kein irreführender Rechte-Hinweis erscheinen.
|
||||
Ergebnis: Benutzer ohne Aktivierung von „Belegdatum verwenden“ sehen keinen Rechte-Hinweis, auch wenn ihnen das Recht fehlt.
|
||||
Belege:
|
||||
- [PRIMÄR] Commit baa9e7bd9b632780484edaec2330c521d39fc70b, TimerBillingSettingsPageViewModel.cs - Begründung: `if(!this.UseBillingDate) { this.BillingDateIsEnabled = false; this.ShowBillingDateNoteEnabledInfo = false; return; }` wörtlich im Diff.
|
||||
Prüfidee: UseBillingDate=false, Benutzer ohne Recht: Kein Info-Icon sichtbar. UseBillingDate=true, gleicher Benutzer: Info-Icon erscheint.
|
||||
Tracelinks: StRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne F: Helpdesk / Ticketsystem
|
||||
|
||||
### SwRS-017
|
||||
```
|
||||
ID: SwRS-017
|
||||
Titel: Automatische Skalierung und Formatkonvertierung von Status-Icons
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (HelpdeskStatusBL)
|
||||
Vorbedingung: Administrator lädt ein Icon für einen Ticket-Status hoch.
|
||||
Fakt: `SaveHelpdeskStatus` skaliert ein hochgeladenes Icon serverseitig zwingend auf 16x16 Pixel und konvertiert es nach BMP, mit dem im Code dokumentierten Grund, dass „c-entron Delphi“ (Altsystem-Komponente) kein JPG verarbeiten kann (HelpdeskStatusBL.cs Zeilen 52-73).
|
||||
Aussage: Die Software soll jedes für einen Ticket-Status hochgeladene Icon unabhängig vom Originalformat und der Originalgröße automatisch auf 16x16 Pixel BMP normalisieren, um Kompatibilität mit einer separaten Delphi-basierten Altkomponente sicherzustellen.
|
||||
Ergebnis: Icons sind unabhängig von der Upload-Quelle einheitlich klein und in einem von der Legacy-Komponente lesbaren Format gespeichert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskStatusBL.cs Zeilen 56-66 - Begründung: Wörtlicher Code inkl. erläuterndem Kommentar zur Delphi-Inkompatibilität eingesehen; deutlicher Hinweis auf plattformübergreifende Altlast.
|
||||
Prüfidee: Upload eines 512x512-PNG-Icons resultiert in einem gespeicherten 16x16-BMP-Icon.
|
||||
Tracelinks: StRS-011
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (Kompatibilität mit Delphi-Altsystem – im Zielsystem einer Web/SaaS-Neuimplementierung voraussichtlich entfallend, da keine Delphi-Komponente mehr existiert)
|
||||
```
|
||||
|
||||
### SwRS-018
|
||||
```
|
||||
ID: SwRS-018
|
||||
Titel: Referenzzählung über zwei unabhängige Entitäten vor Statuslöschung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Administrator löscht einen Ticket-Status.
|
||||
Fakt: `DeleteHelpdeskStatus` zählt unabhängig voneinander Datensätze in `HelpdeskCompact` (Tickets) und `TaskManagementHelpdeskAction` (Task-Aktionen, gefiltert auf `f.State != null && f.State.I3D == status.I3D`) und verweigert die Löschung, wenn die Summe größer 0 ist (HelpdeskStatusBL.cs Zeilen 75-104).
|
||||
Aussage: Die Software soll vor dem Löschen eines Ticket-Status sowohl direkte Ticket-Referenzen als auch Referenzen aus dem Taskmanagement prüfen, da beide Entitäten unabhängig voneinander auf denselben Status verweisen können.
|
||||
Ergebnis: Ein Status, der nur in Tasks (nicht in Tickets) verwendet wird, ist ebenso vor Löschung geschützt wie ein rein in Tickets verwendeter Status.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskStatusBL.cs Zeilen 75-104 - Begründung: Beide Count-Abfragen und die Fehlermeldungskomposition wörtlich eingesehen.
|
||||
Prüfidee: Status wird nur in einer TaskManagementHelpdeskAction referenziert (0 Tickets): Löschung wird dennoch verweigert mit Meldung „... wird in 1 Task verwendet.“
|
||||
Tracelinks: StRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne G: EDI
|
||||
|
||||
### SwRS-019
|
||||
```
|
||||
ID: SwRS-019
|
||||
Titel: Partial-Class-Organisation je Lieferantenformat
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Entwickler
|
||||
Vorbedingung: -
|
||||
Fakt: Die Klasse `SupplierEdiBL` ist über sechs Dateien als `partial class` auf Lieferanten verteilt: SupplierEdiBL.cs (Kern inkl. ApplyDistriToCentron), .Also.cs, .AlsoCH.cs, .Alltron.cs, .Herweck.cs, .Komsa.cs, .Opentrans.cs (Dateisystem-Verifikation, edi-architecture.md).
|
||||
Aussage: Die Software soll lieferantenspezifische EDI-Parsing- und Mapping-Logik strikt in eigenen Partial-Class-Dateien kapseln, sodass die Kernklasse SupplierEdiBL.cs unabhängig von der Anzahl unterstützter Lieferanten übersichtlich bleibt.
|
||||
Ergebnis: Ein neuer Lieferant erfordert eine neue Datei, keine Änderung an bestehenden Lieferanten-Dateien.
|
||||
Belege:
|
||||
- [PRIMÄR] Dateisystem: src/backend/Centron.BL/EDI/SupplierEDI/{SupplierEdiBL.cs, .Also.cs, .AlsoCH.cs, .Alltron.cs, .Herweck.cs, .Komsa.cs, .Opentrans.cs} - Begründung: Alle sieben Dateien wurden per Verzeichnisauflistung bestätigt.
|
||||
Prüfidee: Hinzufügen eines neuen Lieferanten erfordert laut Doku nur eine neue Datei `SupplierEdiBL.NeuerLieferant.cs` plus Erweiterung des Dispatch in ApplyDistriToCentron.
|
||||
Tracelinks: StRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne H: Authentifizierung & Lizenzierung
|
||||
|
||||
### SwRS-020
|
||||
```
|
||||
ID: SwRS-020
|
||||
Titel: OpenIdConnectAuthObject kapselt Claim-Zugriff typsicher
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `OpenIdConnectAuthObject` definiert `SubjectIdentifierKey="oid"` und `EmailKey="preferred_username"` als Konstanten mit Verweis auf die offizielle Microsoft-Dokumentation im Kommentar; `SubjectIdentifier`/`Email` sind berechnete Properties, die den jeweiligen Claim aus der `ClaimsIdentity` extrahieren (OpenIdConnectAuthenticator.cs Zeilen 14-23).
|
||||
Aussage: Die Software soll den Zugriff auf sicherheitsrelevante JWT-Claims (oid, preferred_username) über benannte Konstanten kapseln, statt Claim-Namen als Magic Strings im Authentifizierungscode zu verstreuen.
|
||||
Ergebnis: Eine Änderung des verwendeten Claim-Namens erfordert nur eine zentrale Anpassung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/OpenIdConnectAuthenticator.cs Zeilen 14-23 - Begründung: Wörtlicher Code inkl. Dokumentationslink eingesehen.
|
||||
Prüfidee: Unit-Test instanziiert OpenIdConnectAuthObject mit einer ClaimsIdentity, die einen "oid"-Claim enthält: SubjectIdentifier liefert exakt diesen Wert.
|
||||
Tracelinks: SyRS-016
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-021
|
||||
```
|
||||
ID: SwRS-021
|
||||
Titel: Lizenzprüfung, Authentifizierungsstatus und Claim-Vorhandensein als geordnete Kette abweisender Vorbedingungen
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `AuthenticateInternal()` prüft in fester Reihenfolge: (1) Lizenz vorhanden, (2) `Auth.Identity.IsAuthenticated`, (3) `Auth.SubjectIdentifier is not null`, erst danach erfolgt der Datenbank-Lookup; jede Stufe loggt bei Fehlschlag eine Warnung mit E-Mail und vollständigem AuthObject-Kontext (OpenIdConnectAuthenticator.cs Zeilen 39-63).
|
||||
Aussage: Die Software soll die OIDC-Authentifizierung als Kette einzeln geprüfter, früh abbrechender Vorbedingungen implementieren und jeden Fehlschlag mit Kontextinformationen protokollieren, bevor ein Datenbankzugriff erfolgt.
|
||||
Ergebnis: Ungültige oder unvollständige Tokens verursachen keinen Datenbankzugriff; jeder Fehlschlag ist im Log nachvollziehbar (inkl. RequestId).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/OpenIdConnectAuthenticator.cs Zeilen 39-63 - Begründung: Vollständiger Methodenkörper mit allen drei Guard-Klauseln und Logger.Warn-Aufrufen wörtlich eingesehen.
|
||||
Prüfidee: Token ohne oid-Claim führt zu Log-Eintrag „Could not find subject identifier 'oid' in JWT claims.“ ohne DB-Zugriff (verifizierbar per SQL-Profiler/Mock).
|
||||
Tracelinks: SyRS-015, SyRS-016
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SwRS-022
|
||||
```
|
||||
ID: SwRS-022
|
||||
Titel: Ticket-Ablaufdatum-Aktualisierung mit Schreibreduktion (5-Minuten-Schwelle)
|
||||
Ebene: SwRS
|
||||
Typ: Performance-Effizienz
|
||||
Akteur: System (TicketBL)
|
||||
Vorbedingung: Ein bestehendes Ticket wird bei einer weiteren Anfrage erneut validiert.
|
||||
Fakt: `RefreshTicketExpireDate` berechnet das neue potenzielle Ablaufdatum, schreibt es aber nur dann in die Datenbank, wenn die Differenz zum bisherigen `ticket.ExpiryDate` mindestens 5 Minuten beträgt; ein expliziter Code-Kommentar erklärt dies als Optimierung zur Reduktion der Schreibhäufigkeit sowie eine bekannte Nebenwirkung („the ticket will be expired on the second method-call“ bei falscher Anwendung) (TicketBL.cs Zeilen 113-133).
|
||||
Aussage: Die Software soll die Aktualisierung des Ticket-Ablaufdatums in der Datenbank auf höchstens eine Schreiboperation pro 5-Minuten-Fenster begrenzen, um die Schreiblast bei häufigen API-Aufrufen zu reduzieren.
|
||||
Ergebnis: Bei sehr häufigen Anfragen (z. B. Polling) wird das Ablaufdatum nicht bei jeder Anfrage in der Datenbank aktualisiert, sondern höchstens alle 5 Minuten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs Zeilen 113-133 - Begründung: Vollständiger Methodencode inkl. erläuternder Inline-Kommentare zur Design-Entscheidung und einer im Kommentar selbst dokumentierten Randbedingung/Fallstrick eingesehen.
|
||||
Prüfidee: Zwei aufeinanderfolgende API-Aufrufe im Abstand von 1 Minute lösen nur eine tatsächliche DB-Schreiboperation für ExpiryDate aus (per SQL-Profiler nachweisbar).
|
||||
Tracelinks: SyRS-017
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (im Kommentar selbst als potenzielle Fehlerquelle bei falscher Verwendung dokumentiert – Kandidat für Härtung im Zielsystem)
|
||||
```
|
||||
|
||||
### SwRS-023
|
||||
```
|
||||
ID: SwRS-023
|
||||
Titel: Unterschiedliche Standard-Sitzungsdauer je Applikationstyp
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `GetExpireDate(ApplicationKind)` liefert je nach Applikationstyp unterschiedliche Werte: Standardfall `TicketExpireInMinutes=30`, ein konfigurierbarer, aber mindestens 30-minütiger Wert für einen weiteren Fall (`Math.Max(setting.GetValueOrDefault(TicketExpireInMinutes), TicketExpireInMinutes)`), sowie `TicketExpire24HoursInMinutes=1440` für einen dritten Fall (TicketBL.cs Zeilen 136-163).
|
||||
Aussage: Die Software soll die Sitzungsdauer abhängig vom Typ der sich anmeldenden Applikation unterschiedlich lang bemessen, wobei ein administrativ konfigurierbarer Wert nie unter das Sicherheitsminimum von 30 Minuten fallen darf.
|
||||
Ergebnis: Applikationen mit höherem Bedienkomfort-Bedarf (z. B. Dauerbetrieb) erhalten längere Sitzungen, ohne dass ein Administrator versehentlich eine zu kurze Mindestdauer konfigurieren kann.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs Zeilen 136-163 - Begründung: Vollständiger switch-artiger Methodenkörper mit den drei Fällen und der Math.Max-Untergrenze wörtlich eingesehen.
|
||||
- [HYPOTHESE] Welcher ApplicationKind konkret den 1440-Minuten-Fall bzw. den konfigurierbaren Fall auslöst - Begründung zur Kennzeichnung: Die switch-Bedingungen (ApplicationKind-Werte) selbst wurden im Rahmen dieser Iteration nicht zeilengenau exzerpiert, nur die drei Ergebniszweige.
|
||||
Prüfidee: Login mit ApplicationKind, der dem 24h-Fall zugeordnet ist, erzeugt ein Ticket mit ExpiryDate = jetzt + 1440 Minuten.
|
||||
Tracelinks: SyRS-017
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne I: Bedienbarkeit / Cross-Cutting
|
||||
|
||||
### SwRS-024
|
||||
```
|
||||
ID: SwRS-024
|
||||
Titel: Manuelles Nachzeichnen des Aktiv-Indikators als DevExpress-Workaround
|
||||
Ebene: SwRS
|
||||
Typ: nicht-funktional (ISO/IEC 25010: Benutzbarkeit)
|
||||
Akteur: System (WPF-Präsentationsschicht)
|
||||
Vorbedingung: Ribbon ist minimiert und ein Modul-Tab ist ausgewählt.
|
||||
Fakt: Laut Commit-Beschreibung wird die Unterstreichung der Caption durch eigenen Zeichencode ergänzt, weil DevExpress den Auswahlindikator bei minimiertem Ribbon nicht anzeigt; die Änderung wurde zusätzlich durch „loosening the cast to DependencyObject“ korrigiert (zweiter Commit-Teil), was auf eine ursprünglich zu strikte Typannahme im ersten Fix-Versuch hindeutet.
|
||||
Aussage: Die Software soll die fehlende native Unterstützung der verwendeten UI-Bibliothek (DevExpress RibbonControl) für einen Auswahlindikator im minimierten Zustand durch eine eigene, robuste (typtolerante) Zeichenroutine kompensieren.
|
||||
Ergebnis: Der Aktiv-Indikator wird zuverlässig gezeichnet, auch wenn das visuelle Element nicht exakt vom erwarteten Typ ist.
|
||||
Belege:
|
||||
- [KONTEXT] Commit 8dd17c7d1244c02ef57ee3f94a42249a056c74cd, beide Commit-Nachrichten („fix: show active tab indicator...“ und „Fixed by loosening the cast to DependencyObject and renaming the handler“) - Begründung: Zwei-stufige Commit-Historie belegt iterative Fehlerbehebung; Ticketreferenz 150766 verknüpft dies mit einem realen Anwenderproblem.
|
||||
Prüfidee: Ribbon minimiert, verschiedene Module (auch mit abweichender visueller Struktur/Custom-Templates) angewählt: Unterstreichung erscheint in allen Fällen ohne Cast-Exception.
|
||||
Tracelinks: StRS-017, SyRS-018
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Ende SwRS. Konsolidierte Rückverfolgbarkeit in [Traceability.md](Traceability.md), offene Annahmen in [Hypothesen.md](Hypothesen.md).*
|
||||
+417
@@ -0,0 +1,417 @@
|
||||
# System Requirements Specification (SyRS)
|
||||
|
||||
Systemverhalten, Schnittstellen sowie Performance- und Sicherheitsanforderungen gemäß ISO/IEC/IEEE 29148:2018, abgeleitet aus den Stakeholder-Anforderungen in [StRS.md](StRS.md). Nicht-funktionale Anforderungen sind zusätzlich den Qualitätsmerkmalen der ISO/IEC 25010 zugeordnet (Feld `Typ` bzw. Kommentar im Fließtext).
|
||||
|
||||
---
|
||||
|
||||
## Domäne A: Rechte- und Berechtigungsverwaltung
|
||||
|
||||
### SyRS-001
|
||||
```
|
||||
ID: SyRS-001
|
||||
Titel: Zentrale Rechteprüfung vor jeder geschützten Operation
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (BL-Schicht), IT-Administrator
|
||||
Vorbedingung: Ein Benutzer ist angemeldet und ruft eine rechtebehaftete Aktion auf.
|
||||
Fakt: Die Business-Logic-Schicht bietet mit AppRightsBL.CheckRightsFromUser(currentUserI3D, rightIds) eine zentrale Prüfmethode, die eine Liste tatsächlich vorhandener Rechte zurückliefert; aufrufender Code muss das Ergebnis explizit auswerten (docs/guides/development/check-userrights.md, Beispiel aus AccountBL.cs).
|
||||
Aussage: Das System soll vor Ausführung einer rechtebehafteten Operation serverseitig prüfen, ob der angemeldete Benutzer über das erforderliche Recht verfügt, und die Operation bei fehlendem Recht mit einer aussagekräftigen Fehlermeldung ablehnen.
|
||||
Ergebnis: Operationen ohne ausreichendes Recht werden mit Result.AsError(...) abgelehnt, nicht stillschweigend ausgeführt.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/guides/development/check-userrights.md Abschnitt „In BL“ - Begründung: Zeigt Originalcode-Ausschnitt aus AccountBL.cs mit AppRightsBL.CheckRightsFromUser(...) und anschließender if(...Contains(...) == false) return Result.AsError(...)-Prüfung; Musterbeleg für den durchgesetzten Mechanismus.
|
||||
- [KONTEXT] docs/guides/development/check-userrights.md Abschnitte „In viewmodels“, „For modules“ - Begründung: Zeigt zusätzliche, redundante Prüfpfade (CentronCache.Instance.CurrentUserAppRights, Helper.HasRights) auf UI-Ebene – deutet auf clientseitige UX-Vorprüfung zusätzlich zur serverseitigen Durchsetzung hin (siehe Konsolidierungshinweis SwRS-003).
|
||||
Prüfidee: Direkter Webservice-Aufruf (unter Umgehung der UI) einer rechtebehafteten Methode ohne das erforderliche Recht muss serverseitig abgelehnt werden, auch wenn die UI die Aktion nicht anbietet.
|
||||
Tracelinks: StRS-001
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-002
|
||||
```
|
||||
ID: SyRS-002
|
||||
Titel: Datenfilterung nach Filial-/Eigentümerkontext bei einschränkenden Rechten
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (Datenzugriffsschicht)
|
||||
Vorbedingung: Benutzer besitzt ein „restricting right“ zusätzlich zum Grundrecht.
|
||||
Fakt: Für Helpdesk sind mindestens vier eigenständige einschränkende Rechte dokumentiert und mit eigener I3D versehen (SHOW_HELPDESK_ONLY_OWN=20400340, SHOW_HELPDESK_ONLY_OWN_BRANCH, ASSIGN_HELPDESK_ONLY_TO_OWN_DEPARTMENTS, CREATE_HELPDESK_ONLY_OWN_BRANCH) (CentronRights.md, UserRightsConst.cs).
|
||||
Aussage: Das System soll bei Vorliegen eines einschränkenden Rechts serverseitige Abfragen/Filter automatisch um die entsprechende Bedingung (eigene Datensätze, eigene Filiale, eigene Abteilung) ergänzen, bevor Ergebnislisten an den Client geliefert werden.
|
||||
Ergebnis: Ergebnislisten enthalten nur Datensätze, die der eingeschränkte Benutzer laut Regel sehen darf; keine nachträgliche reine UI-Filterung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs Zeilen 1959-1972 - Begründung: Bestätigt Existenz und Nummerierung der referenzierten Rechte-Konstanten im durchgesetzten Rechtekatalog.
|
||||
- [SEKUNDÄR] CentronRights.md Abschnitte 1.1-1.2, 2.1, 4 - Begründung: Fachliche Klartext-Beschreibung der erwarteten Filterwirkung je Recht.
|
||||
- [HYPOTHESE] Konkrete Implementierung der Filterlogik (z. B. in HelpdeskBL/HelpdeskSearchFilter) - Begründung zur Kennzeichnung: Die tatsächliche Query-Filterung wurde in dieser Iteration nicht im Code verifiziert, nur die Rechte-Definition und die fachliche Erwartungshaltung; siehe Analysebericht.md (Bereich Helpdesk: Suchfilter nicht vertieft).
|
||||
Prüfidee: Zwei Support-Mitarbeiter unterschiedlicher Filialen mit SHOW_HELPDESK_ONLY_OWN_BRANCH sehen bei identischer Suchanfrage jeweils nur Tickets ihrer eigenen Filiale.
|
||||
Tracelinks: StRS-002
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne B: Belegwesen
|
||||
|
||||
### SyRS-003
|
||||
```
|
||||
ID: SyRS-003
|
||||
Titel: Einheitliche Persistenzstruktur Kopf/Position je Belegart
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (Datenbank)
|
||||
Vorbedingung: -
|
||||
Fakt: Jede Belegart besitzt ein Tabellenpaar *Kopf/*Pos (z. B. AngKopf/AngPos, RechKopf/RechPos, VertragKopf/VertragPos) sowie korrespondierende, englischsprachige Views (Offers/OfferItems, Invoices/InvoiceItems, ...) für den Anwendungszugriff (receipts-backend-architecture.md).
|
||||
Aussage: Das System soll für jede Belegart ein Kopf-/Positionsschema mit klarer 1:n-Beziehung (KopfI3D-Fremdschlüssel) bereitstellen und den lesenden Zugriff über sprechende, englischsprachige Datenbank-Views kapseln.
|
||||
Ergebnis: Anwendungscode greift konsistent über Views zu, unabhängig von den historisch gewachsenen deutschen Tabellennamen.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md Abschnitt „Database Schema“ - Begründung: Vollständige Tabellen-/View-Matrix für 7 Belegarten dokumentiert; Konsistenzprüfung gegen ReceiptBase.cs (StRS-003) stützt Plausibilität, DB-Schema selbst wurde nicht per SQL-Skript eingesehen (keine .sql-Dateien im Repository gefunden).
|
||||
Prüfidee: SELECT * FROM Invoices liefert dieselben fachlichen Felder wie eine direkte Abfrage auf RechKopf, jedoch mit englischen Spaltennamen.
|
||||
Tracelinks: StRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-004
|
||||
```
|
||||
ID: SyRS-004
|
||||
Titel: Zweistufiger Speicherpfad über Legacy-Repositories
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (Persistenzschicht)
|
||||
Vorbedingung: Ein Beleg wird gespeichert.
|
||||
Fakt: Belegspeicherungen laufen nicht ausschließlich über das moderne NHibernate-Mapping, sondern zusätzlich über belegtyp-spezifische SaveReceipt*Repository-Klassen, die Werte in „temporäre“ Legacy-Entities synchronisieren (SynchronizeReceiptData für Kopf-, SynchronizeReceiptItemData für Positionsfelder), bevor in die Datenbank geschrieben wird (receipts-backend-architecture.md, „Critical Save Warning“).
|
||||
Aussage: Das System soll sicherstellen, dass jedes neu hinzugefügte, persistierte Beleg-Feld sowohl im modernen Entity-/View-Mapping als auch im zugehörigen SaveReceipt*Repository synchronisiert wird, da sonst Werte zwar lesbar, aber nicht speicherbar sind.
|
||||
Ergebnis: Neue Felder sind konsistent lese- und schreibbar; keine stillen Datenverluste beim Speichern.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md Abschnitt „Critical Save Warning“ - Begründung: Explizite Warnung der Entwicklerdokumentation vor genau diesem Fehlerbild, weist auf einen bekannten strukturellen Schwachpunkt/Workaround-Charakter der Architektur hin.
|
||||
- [HYPOTHESE] Konkreter Code von SaveReceiptInvoiceRepository.SynchronizeReceiptData - Begründung zur Kennzeichnung: Datei wurde in dieser Iteration nicht geöffnet; Aussage stützt sich ausschließlich auf Entwicklerdokumentation (Tiefe siehe Analysebericht.md).
|
||||
Prüfidee: Ein neues Rechnungsfeld wird nur im View/Entity ergänzt (nicht im Repository): Wert lädt korrekt, geht aber nach dem nächsten Speichervorgang verloren (Regressionstest).
|
||||
Tracelinks: StRS-003
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
### SyRS-005
|
||||
```
|
||||
ID: SyRS-005
|
||||
Titel: Vollständige 1:1-Versionierung bei jeder Belegänderung
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (Versionierungsmechanismus)
|
||||
Vorbedingung: Ein bestehender Beleg wird geändert und eine neue Version angelegt.
|
||||
Fakt: Der Mechanismus AssetHeadDAO.SaveAssetVersion kopiert vor der Änderung alle Spalten des Kopf- und Positionsdatensatzes 1:1 in die zugehörige *Versions-Tabelle inkl. zusätzlicher Spalten OriginalI3D und (bei Positionen) KopfVersionsI3D (receipts-backend-architecture.md, contracts-backend.md).
|
||||
Aussage: Das System soll bei jeder Versionierung eines Belegs sämtliche Kopf- und Positionsspalten vollständig in die Versionstabelle kopieren, ohne Datenverlust gegenüber dem Ursprungszustand.
|
||||
Ergebnis: Jede historische Version ist als vollständiger, eigenständiger Datensatz abrufbar.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md Abschnitt „Version Table Maintenance Process“ inkl. SQL-Beispiel - Begründung: Zeigt konkretes (wenn auch generisches/beispielhaftes) INSERT-Statement-Muster, konsistent mit paralleler Beschreibung in contracts-backend.md für VertragKopf/VertragPos (zwei unabhängige Dokumentationsquellen bestätigen dasselbe Muster).
|
||||
- [HYPOTHESE] Tatsächlicher Code von AssetHeadDAO.SaveAssetVersion - Begründung zur Kennzeichnung: Klasse wurde namentlich referenziert, aber die Datei wurde in dieser Iteration nicht geöffnet (Analysetiefe siehe Analysebericht.md).
|
||||
Prüfidee: Nach zwei aufeinanderfolgenden Änderungen an einem Vertrag existieren zwei Datensätze in VertragKopfVersions mit korrektem OriginalI3D-Bezug und vollständigen historischen Werten.
|
||||
Tracelinks: StRS-004
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne C: Web-Angebot & digitale Signatur
|
||||
|
||||
### SyRS-006
|
||||
```
|
||||
ID: SyRS-006
|
||||
Titel: Token-basierter, anonymer Web-Zugriff auf Belege
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Kunde (Web-Login), System (Nexus)
|
||||
Vorbedingung: Ein Web-Angebot wurde für einen Beleg generiert.
|
||||
Fakt: Die Nexus-Route ist als `@page "/weboffer/{Token}"` implementiert; der Zugriff erfolgt ausschließlich über einen in der URL enthaltenen Token, ohne klassischen Benutzerlogin (WebReceiptOverview.razor Zeile 1, CentronService.GetReceiptForWeb(Token)).
|
||||
Aussage: Das System soll den Zugriff auf ein Web-Angebot ausschließlich über einen unvorhersehbaren, dem Beleg zugeordneten Token gewähren, ohne dass der Kunde ein reguläres Benutzerkonto benötigt.
|
||||
Ergebnis: Nur Inhaber des Links (Token) können das jeweilige Angebot einsehen/bearbeiten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor Zeile 1, 494, 576-612 - Begründung: Routing-Attribut und LoadReceipt()-Methode zeigen direkten Aufruf CentronService.GetReceiptForWeb(Token) ohne vorgelagerte Authentifizierung.
|
||||
- [HYPOTHESE] Entropie/Erzeugungsverfahren des Tokens (kryptographische Stärke, Ablaufmechanismus außerhalb des Signatur-Flows) - Begründung zur Kennzeichnung: Die Token-Erzeugung für Web-Angebote selbst (im Unterschied zum Signatur-SharedDocument-Token, siehe SwRS-011) wurde in dieser Iteration nicht im Code lokalisiert/verifiziert.
|
||||
Prüfidee: Zugriff auf `/weboffer/{Token}` mit geratenem/ungültigem Token liefert Fehlermeldung „Beleg konnte nicht geladen werden.“ statt Fremddaten.
|
||||
Tracelinks: StRS-005
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
### SyRS-007
|
||||
```
|
||||
ID: SyRS-007
|
||||
Titel: Zustandsmaschine für den Web-Angebots-Lebenszyklus
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein Web-Angebot existiert.
|
||||
Fakt: WebReceiptState kennt die durchgesetzten Werte InProcess, FirstLoaded, AcceptFullWebReceipt, AcceptWebReceiptWithChangeRequests, Rejected, SendToCustomer, WebOfferSign, WebOfferSignedWithoutSignature, WebReceiptShutDown; UI-Aktionen (Annehmen/Ablehnen) sind nur erlaubt, solange der Zustand InProcess oder FirstLoaded ist (WebReceiptState.cs, WebReceiptOverview.razor Zeile 593-600).
|
||||
Aussage: Das System soll Kundeninteraktionen mit einem Web-Angebot (Mengenänderung, Annahme, Ablehnung) ausschließlich in den Zuständen InProcess und FirstLoaded zulassen und nach jeder finalen Aktion in einen Endzustand überführen, der weitere Änderungen sperrt.
|
||||
Ergebnis: Ein bereits angenommenes oder abgelehntes Web-Angebot kann nicht nachträglich erneut verändert werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/WebReceipt/WebReceiptState.cs - Begründung: Vollständiges Enum im Quellcode eingesehen.
|
||||
- [PRIMÄR] src/nexus/CentronNexus/WebOffer/WebReceiptOverview.razor Zeilen 593-600 - Begründung: `_canExecuteAction = Receipt.AllowAcceptReceipt && isWebReceiptInProcess` mit isWebReceiptInProcess als Prüfung auf genau die zwei zulässigen Zustände; direkte UI-seitige Durchsetzung.
|
||||
Prüfidee: Zweiter Aufruf von ChangeWebReceiptState nach bereits erfolgter Annahme wird serverseitig abgelehnt (Statuscheck), nicht nur clientseitig durch deaktivierte Buttons verhindert.
|
||||
Tracelinks: StRS-005
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-008
|
||||
```
|
||||
ID: SyRS-008
|
||||
Titel: Signaturerzwingung als serverseitige Vorbedingung für Auftragsanlage
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Kunde hat Web-Angebot angenommen.
|
||||
Fakt: ReceiptBL.AcceptWebReceipt prüft AllowAcceptReceipt (Guard-Exception bei false) und verzweigt danach hart zwischen signaturfreiem und signaturpflichtigem Pfad; im signaturpflichtigen Pfad wird ein SharedDocument-Token erzeugt und der Auftrag erst nach separatem Signaturvorgang ausgelöst (ReceiptBL.cs Zeilen 6256-6309).
|
||||
Aussage: Das System soll die Entscheidung „Signatur erforderlich ja/nein“ serverseitig anhand persistierter Konfiguration (nicht anhand von Client-Eingaben) treffen und einen signaturpflichtigen Auftrag erst nach Abschluss des Signaturvorgangs technisch auslösen.
|
||||
Ergebnis: Ein manipulierter Client kann die Signaturpflicht nicht umgehen, da die Prüfung serverseitig in ReceiptBL erfolgt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs Zeilen 6197-6198, 6260-6264 - Begründung: Zwei unabhängige Guard-Prüfungen auf AllowAcceptReceipt sowie die Verzweigung auf AllowAcceptReceiptWithoutSignature liegen serverseitig in der BL, nicht im Blazor-Client.
|
||||
Prüfidee: Manipulierter API-Request, der versucht, direkt einen Auftrag ohne vorherigen Signatur-Callback zu erzeugen, wird von ReceiptBL abgelehnt, da der Beleg noch im Zustand WebOfferSign verharrt.
|
||||
Tracelinks: StRS-006
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne D: Verträge
|
||||
|
||||
### SyRS-009
|
||||
```
|
||||
ID: SyRS-009
|
||||
Titel: Zeitgesteuerte automatische Fakturierung fälliger Verträge
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (AutomaticFacturaBL)
|
||||
Vorbedingung: Vertrag mit AutomatedBilling=true erreicht laut BillingIntervalKind/-Duration seinen nächsten Abrechnungstermin.
|
||||
Fakt: AutomaticFacturaBL.Contracts ist laut Dokumentation für automatische Rechnungserstellung, RMM-Integration, Berechnung der Abrechnungsparameter und Unterstützung mehrerer Intervalle zuständig (contracts-backend.md Abschnitt „AutomaticFacturaBL.Contracts“); Datei-Existenz wurde verifiziert.
|
||||
Aussage: Das System soll fällige Verträge periodisch (z. B. per Hintergrundjob) identifizieren und für jeden fälligen Vertrag automatisiert eine Folgerechnung erzeugen, ohne dass ein Mitarbeiter den Vorgang manuell anstoßen muss.
|
||||
Ergebnis: Zum Fälligkeitstag liegt eine Rechnung vor; LastSubsequentBillingDate wird aktualisiert.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md Abschnitt „Automated Billing Process“ - Begründung: Beschreibt den 3-stufigen Ablauf (Contract Evaluation, Invoice Generation, Post-Processing) nur auf Dokumentationsebene; der auslösende Scheduler/Trigger-Mechanismus (Windows-Dienst, Cronjob o.ä.) wurde nicht im Code identifiziert.
|
||||
- [HYPOTHESE] Konkreter Trigger-Mechanismus (Zeitplan, Service) für die automatische Abrechnung - Begründung zur Kennzeichnung: Kein Scheduler/Hintergrunddienst-Code in dieser Iteration untersucht (vgl. Centron.Host.WindowsService als Kandidat, nicht vertieft).
|
||||
Prüfidee: Vertrag mit BillingIntervalKind=Monthly, AutomatedBilling=true: Am Fälligkeitstag entsteht ohne manuellen Eingriff eine neue Rechnung.
|
||||
Tracelinks: StRS-008
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
### SyRS-010
|
||||
```
|
||||
ID: SyRS-010
|
||||
Titel: Vertragskontingent als abrechnungsrelevanter Zustand
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (ReceiptContractBL)
|
||||
Vorbedingung: Leistungen/Zeiten werden einem kontingentierten Vertrag zugeordnet.
|
||||
Fakt: ReceiptContract führt die Felder ContingentUsedHours, ContingentUsedAmount, ContingentBalanceUsedHours/-Amount als persistente Zustandsgrößen; ReceiptContractBL bietet ContractContingentBalanceCalculation() und UpdateContractContingentBalanceCalculationForReceiptChange() (contracts-backend.md).
|
||||
Aussage: Das System soll bei jeder abrechnungsrelevanten Änderung eines Beleges, der einem kontingentierten Vertrag zugeordnet ist, den Kontingentverbrauch neu berechnen und persistieren.
|
||||
Ergebnis: Der aktuelle Kontingentverbrauch ist jederzeit konsistent mit den zugeordneten Belegen.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md Abschnitte „Contingent Management“, „Contingent and Billing“ - Begründung: Auflistung konkreter Methodennamen und Felder, jedoch ohne Einsicht in die Berechnungsformel selbst.
|
||||
- [HYPOTHESE] Exakte Berechnungsformel/Rundungsregeln - Begründung zur Kennzeichnung: nicht verifiziert (siehe StRS-009 gleiche Einschränkung).
|
||||
Prüfidee: Änderung der Menge eines kontingentrelevanten Beleg-Items löst Neuberechnung von ContingentBalanceUsedHours aus.
|
||||
Tracelinks: StRS-009
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne E: Zeiterfassung & Timer-Billing
|
||||
|
||||
### SyRS-011
|
||||
```
|
||||
ID: SyRS-011
|
||||
Titel: Zentrale, nicht modul-lokale Rechtsquelle für Belegdatum-Änderbarkeit
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (CentronCache/ReceiptSettings)
|
||||
Vorbedingung: Timer-Billing-Assistent wird geöffnet.
|
||||
Fakt: Die Berechtigungsinformation wird nicht neu berechnet, sondern aus einem bereits geladenen, zentralen Cache-Objekt gelesen: `CentronCache.Instance.ReceiptSettings?.CanChangeDateInInvoices` bzw. `...CanChangeDateInDeliveryLists` (TimerBillingSettingsPageViewModel.cs, Methode UpdateBillingDateIsEnabled()).
|
||||
Aussage: Das System soll die Information, ob ein Benutzer Beleg-/Lieferscheindaten nachträglich ändern darf, zentral in den Beleg-Einstellungen (ReceiptSettings) vorhalten und in allen Belegkontexten (u. a. Timer-Billing) konsistent auswerten.
|
||||
Ergebnis: Eine Änderung des zugrunde liegenden Rechts wirkt sich konsistent auf alle Stellen aus, die CanChangeDateInInvoices/-DeliveryLists auswerten, ohne modulspezifische Sonderlogik.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs Methode UpdateBillingDateIsEnabled() - Begründung: Direkter Lesezugriff auf CentronCache.Instance.ReceiptSettings, keine lokale Neuimplementierung der Rechteprüfung.
|
||||
- [HYPOTHESE] Ob CanChangeDateInInvoices/-DeliveryLists an anderer Stelle (z. B. reguläre Rechnungserfassung außerhalb Timer-Billing) ebenfalls konsistent ausgewertet wird - Begründung zur Kennzeichnung: nur der Timer-Billing-Aufrufpfad wurde in dieser Iteration verifiziert.
|
||||
Prüfidee: Änderung des zugrunde liegenden Rechts wirkt sich unmittelbar (nach Cache-Refresh) sowohl im Timer-Billing als auch in anderen Belegdatums-Kontexten gleich aus.
|
||||
Tracelinks: StRS-010
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne F: Helpdesk / Ticketsystem
|
||||
|
||||
### SyRS-012
|
||||
```
|
||||
ID: SyRS-012
|
||||
Titel: Anwendungsweite Konfiguration statt Code-Konstanten für Sonderstatus
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (AppSettingsBL)
|
||||
Vorbedingung: -
|
||||
Fakt: Die I3D-Werte für „geschlossen“ und „Standardstatus nach Öffnen“ werden zur Laufzeit aus AppSettingsBL (Tabelle der Anwendungseinstellungen, Schlüssel AppSettingsConst.HelpdeskClosedState / HelpdeskAfterOpenDefaultState) gelesen (HelpdeskStatusBL.cs Zeilen 40-50).
|
||||
Aussage: Das System soll die Zuordnung von Sonderrollen zu Ticket-Status (geschlossen, Standard nach Öffnen) als Anwendungseinstellung persistieren, sodass sie ohne Code-Änderung pro Installation individuell konfigurierbar ist.
|
||||
Ergebnis: Jede c-entron-Installation kann eigene Status als „geschlossen“/„Standard“ definieren.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Support/HelpdeskStatusBL.cs Zeilen 40-50 - Begründung: Beide Methoden lesen den Settingwert per AppSettingsBL(...).GetSettings(...).GetInt(...), kein hartkodierter Status.
|
||||
Prüfidee: Ändern der Anwendungseinstellung HelpdeskClosedState auf einen anderen Status-I3D bewirkt sofort, dass GetClosedHelpdeskStatus() den neuen Status liefert.
|
||||
Tracelinks: StRS-011, StRS-012
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne G: EDI
|
||||
|
||||
### SyRS-013
|
||||
```
|
||||
ID: SyRS-013
|
||||
Titel: Formatunabhängiger Dispatch über einheitliche Schnittstelle
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (SupplierEdiBL), externes Lieferantensystem
|
||||
Vorbedingung: EDI-Dateien wurden heruntergeladen (FTP/SFTP) und liegen als EDIDistriFile-Liste vor.
|
||||
Fakt: ApplyDistriToCentron(List<EDIDistriFile>, SupplierEdiConfigurations, OrderInfo) ist eine einzige öffentliche Einstiegsmethode, die anhand von SupplierEdiConfigurations.EdiDataType/ObjectKind an die passende lieferantenspezifische Partial-Klasse weiterleitet (SupplierEdiBL.cs Zeile 1364, edi-architecture.md).
|
||||
Aussage: Das System soll unabhängig vom konkreten Lieferantenformat eine einheitliche Verarbeitungsschnittstelle bereitstellen, die intern anhand der Konfiguration an die passende Formatimplementierung delegiert.
|
||||
Ergebnis: Neue Lieferantenformate können ergänzt werden, ohne die aufrufende Schnittstelle zu verändern.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/EDI/SupplierEDI/SupplierEdiBL.cs Zeile 1364 - Begründung: Methodensignatur im Quellcode direkt verifiziert.
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md Abschnitt „Core Processing Method“ - Begründung: Beschreibt Verantwortlichkeiten der Methode (Routing, Delegation, Cleanup) im Detail über die reine Signatur hinaus, ohne dass der Methodenkörper selbst gelesen wurde.
|
||||
Prüfidee: Aufruf von ApplyDistriToCentron mit EdiDataType=Alltron delegiert nachweislich an eine SupplierEdiBL.Alltron.cs-Methode (z. B. per Log-Eintrag oder Debugger).
|
||||
Tracelinks: StRS-013
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-014
|
||||
```
|
||||
ID: SyRS-014
|
||||
Titel: Fehlertolerante Teilverarbeitung von EDI-Dokumenten
|
||||
Ebene: SyRS
|
||||
Typ: Zuverlässigkeit
|
||||
Akteur: System (EDILogBL)
|
||||
Vorbedingung: Eine EDI-Datei enthält teilweise fehlerhafte Datensätze.
|
||||
Fakt: Die Dokumentation beschreibt „Partial Processing: Continue processing valid records despite individual failures“ sowie ein strukturiertes Logging über EDILogState (DownloadOK, DownloadError, DownloadTest, Exception, TestException) (edi-architecture.md Abschnitt „Error Handling and Logging“).
|
||||
Aussage: Das System soll bei der Verarbeitung einer EDI-Datei fehlerhafte Einzeldatensätze überspringen/protokollieren, ohne die Verarbeitung der übrigen, gültigen Datensätze der gleichen Datei abzubrechen.
|
||||
Ergebnis: Ein einzelner fehlerhafter Datensatz blockiert nicht die gesamte Lieferung/Bestellung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md Abschnitt „Error Recovery Strategies“ - Begründung: Nur dokumentarisch beschrieben; das tatsächliche Try/Catch- bzw. Skip-Verhalten wurde in keiner konkreten Methode dieser Iteration im Code nachvollzogen.
|
||||
- [HYPOTHESE] Konkretes Verhalten bei fehlerhaftem Einzelsatz (Skip vs. Abbruch der gesamten Datei) - Begründung zur Kennzeichnung: Ohne Code-Verifikation nicht von der Dokumentationsaussage unterscheidbar, ob dies bereits vollständig implementiert oder nur als Zielarchitektur beschrieben ist.
|
||||
Prüfidee: EDI-Testdatei mit einer fehlerhaften und neun korrekten Positionszeilen: Neun Positionen werden verarbeitet, eine wird mit Fehlerprotokoll übersprungen.
|
||||
Tracelinks: StRS-013, StRS-014
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne H: Authentifizierung & Lizenzierung
|
||||
|
||||
### SyRS-015
|
||||
```
|
||||
ID: SyRS-015
|
||||
Titel: Lizenzpflicht als Vorbedingung für alternative Authentifizierung
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (OpenIdConnectAuthenticator)
|
||||
Vorbedingung: Ein Client versucht, sich per Microsoft-ID-Token anzumelden.
|
||||
Fakt: AuthenticateInternal() prüft zuerst LicenseManager.HasLicense(LicenseGuids.OpenIDConnectAuthentication) und bricht bei fehlender Lizenz mit Result<LoggedInUser>.AsError(...) ab, bevor die Identität geprüft wird (OpenIdConnectAuthenticator.cs Zeilen 43-47).
|
||||
Aussage: Das System soll eine OIDC-Anmeldung ausschließlich dann zulassen, wenn für den Mandanten die Lizenz „OpenIDConnectAuthentication“ aktiv ist, unabhängig davon, ob das vorgelegte Microsoft-Token gültig wäre.
|
||||
Ergebnis: Kunden ohne diese Lizenz können sich nicht per Microsoft-Konto anmelden, selbst mit technisch korrektem Token.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/OpenIdConnectAuthenticator.cs Zeilen 43-47 - Begründung: Vollständiger Methodencode eingesehen; Lizenzprüfung ist die erste Bedingung vor jeder weiteren Identitätsprüfung.
|
||||
Prüfidee: Gültiges Microsoft-ID-Token, aber Mandant ohne Lizenz OpenIDConnectAuthentication → Login schlägt mit „No license for OpenIDConnectAuthentication“ fehl.
|
||||
Tracelinks: StRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-016
|
||||
```
|
||||
ID: SyRS-016
|
||||
Titel: Eindeutige Benutzerzuordnung über unveränderlichen externen Identifier
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (OpenIdConnectAuthenticator)
|
||||
Vorbedingung: Lizenzprüfung (SyRS-015) erfolgreich, Token ist authentisch.
|
||||
Fakt: Der Benutzer wird ausschließlich über den `oid`-Claim (Microsoft Entra Object ID) gegen die Spalte OpenIdConnectSubjectIdentifier der Tabelle der App-Benutzer aufgelöst, nicht über E-Mail oder Namen (OpenIdConnectAuthenticator.cs Zeile 61-62, OpenIdConnectAuthObject.SubjectIdentifierKey="oid").
|
||||
Aussage: Das System soll die Zuordnung eines Microsoft-Kontos zu einem c-entron-Benutzer ausschließlich über die unveränderliche Microsoft Object-ID vornehmen, nicht über veränderliche Attribute wie E-Mail-Adresse.
|
||||
Ergebnis: Eine spätere Änderung der Microsoft-E-Mail-Adresse eines Benutzers beeinträchtigt die Anmeldezuordnung nicht.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/Auth/OpenIdConnectAuthenticator.cs Zeilen 17, 21, 61-62 - Begründung: SubjectIdentifierKey ist als "oid" konstant definiert und wird als alleiniges Lookup-Kriterium verwendet (where.OpenIdConnectSubjectIdentifier == Auth.SubjectIdentifier); Email wird nur für Logging verwendet (Zeilen 41, 45, 51, 57, 67, 71), nicht für den DB-Lookup.
|
||||
Prüfidee: Benutzer ändert seine Microsoft-E-Mail-Adresse (oid bleibt gleich): Login funktioniert unverändert.
|
||||
Tracelinks: StRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
### SyRS-017
|
||||
```
|
||||
ID: SyRS-017
|
||||
Titel: Zeitlich befristete, aktivitätsabhängig verlängerte Sitzungen
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (TicketBL)
|
||||
Vorbedingung: Benutzer hat sich erfolgreich angemeldet (unabhängig von Passwort- oder OIDC-Login).
|
||||
Fakt: TicketBL definiert TicketExpireInMinutes=30 als Standard-Sitzungsdauer und TicketExpire24HoursInMinutes=1440 als Sonderfall; RefreshTicketExpireDate verlängert das Ablaufdatum bei Aktivität, aber nur wenn der neue Ablauf mindestens 5 Minuten später liegt als der bisherige, um übermäßige Schreibzugriffe zu vermeiden (TicketBL.cs Zeilen 26-28, 113-133, 136-163).
|
||||
Aussage: Das System soll Sitzungs-Tickets standardmäßig nach 30 Minuten Inaktivität ablaufen lassen, bei fortlaufender Nutzeraktivität aber automatisch verlängern, wobei Verlängerungen aus Effizienzgründen erst ab einer Mindestdifferenz von 5 Minuten tatsächlich in der Datenbank aktualisiert werden.
|
||||
Ergebnis: Inaktive Sitzungen laufen nach spätestens 30 Minuten ab; aktive Sitzungen bleiben ohne erneuten Login nutzbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Logins/TicketBL.cs Zeilen 26-28, 129, 136-163 - Begründung: Konstanten und Verlängerungslogik wurden im vollständigen Methodencode eingesehen und stimmen mit der Kommentierung im Code selbst überein.
|
||||
Prüfidee: Ticket wird nach 31 Minuten Inaktivität bei nachfolgendem API-Call als abgelaufen erkannt und erfordert erneuten Login.
|
||||
Tracelinks: StRS-015
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Domäne I: Nicht-funktionale Anforderungen (ISO/IEC 25010) – Querschnitt
|
||||
|
||||
### SyRS-018
|
||||
```
|
||||
ID: SyRS-018
|
||||
Titel: Sichtbarkeit des aktiven UI-Kontexts unabhängig vom Ribbon-Zustand
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (ISO/IEC 25010: Benutzbarkeit – Erkennbarkeit der Bedienung)
|
||||
Akteur: System (WPF-Präsentationsschicht)
|
||||
Vorbedingung: Ribbon ist minimiert.
|
||||
Fakt: Commit 8dd17c7d12 fügt manuelles Rendering einer Unterstreichung der Modul-Caption hinzu, wenn Ribbon minimiert und Modul aktiv ist, weil das DevExpress-Standardverhalten hier keine Kennzeichnung anzeigt.
|
||||
Aussage: Das System soll unabhängig vom Zustand der Hauptnavigation (Ribbon minimiert/erweitert) eine konsistente visuelle Kennzeichnung des aktiven Bedienkontexts sicherstellen.
|
||||
Ergebnis: Kein Zustand der Oberfläche führt zu vollständigem Verlust der Aktiv-Kennzeichnung.
|
||||
Belege:
|
||||
- [KONTEXT] Commit 8dd17c7d1244c02ef57ee3f94a42249a056c74cd - Begründung: Beschreibt Ursache und Fix; das eigentliche Rendering wurde nicht im Volltext der ModuleResources.xaml nachvollzogen (nur Diff-Stat).
|
||||
Prüfidee: Manuelle UI-Prüfung: Ribbon minimieren, mehrere Module durchklicken, aktives Modul muss stets erkennbar bleiben.
|
||||
Tracelinks: StRS-017
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
### SyRS-019
|
||||
```
|
||||
ID: SyRS-019
|
||||
Titel: Schutz vor unbeabsichtigtem E-Mail-Versand an reale Kunden in Testumgebungen
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (ISO/IEC 25010: Sicherheit – Vertraulichkeit/Schutz vor Fehlbedienung)
|
||||
Akteur: Entwickler, System (Mailversand)
|
||||
Vorbedingung: Anwendung läuft als DEBUG-Build.
|
||||
Fakt: In DEBUG-Builds werden laut DeveloperSecurity.cs alle externen E-Mail-Adressen (nicht auf nexoware.com endend) automatisch durch test@nexoware.com ersetzt; dieses Verhalten ist in RELEASE-Builds nicht aktiv (docs/reference/security/developer-security.md).
|
||||
Aussage: Das System soll in Entwicklungs-/Debug-Umgebungen automatisch verhindern, dass E-Mails an tatsächliche externe (Kunden-)Adressen versendet werden, indem diese durch eine interne Testadresse ersetzt werden.
|
||||
Ergebnis: Versehentlicher Testmailversand an echte Kunden ist im Debug-Modus ausgeschlossen; im Release-Modus liegt die Verantwortung beim Entwickler/Betrieb.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/security/developer-security.md - Begründung: Beschreibt Verhalten konkret mit Bedingung (Debug-only, Domain-Suffix-Prüfung „nexoware.com“), jedoch wurde DeveloperSecurity.cs selbst in dieser Iteration nicht geöffnet.
|
||||
- [HYPOTHESE] Exakte Implementierung (z. B. ob AllowSendingEmailToExternalAddresses zur Laufzeit oder nur per Neukompilierung änderbar ist) - Begründung zur Kennzeichnung: nicht im Code verifiziert.
|
||||
Prüfidee: Debug-Build sendet Testmail an externe.adresse@kunde.de: tatsächlicher Empfänger im Mailserver-Log ist test@nexoware.com.
|
||||
Tracelinks: -
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
*Fortsetzung/Verfeinerung in [SwRS.md](SwRS.md). Gesamtübersicht in [Traceability.md](Traceability.md). Offene Hypothesen konsolidiert in [Hypothesen.md](Hypothesen.md).*
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
# Traceability-Matrix
|
||||
|
||||
Konsolidierte Forward-/Backward-Rückverfolgbarkeit zwischen StRS, SyRS und SwRS. Eine Zeile pro SwRS-Anforderung (feinste Ebene); StRS/SyRS ohne verfeinerte SwRS-Anforderung sind am Ende separat aufgeführt. „Artefaktbeleg (primär)“ nennt jeweils den stärksten Beleg (PRIMÄR wo vorhanden, sonst SEKUNDÄR/KONTEXT/HYPOTHESE gekennzeichnet).
|
||||
|
||||
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (primär) |
|
||||
|---|---|---|---|
|
||||
| StRS-001 | SyRS-001 | SwRS-001 | `UserRightsConst.cs` (Zeilen 1-20) |
|
||||
| StRS-001 | SyRS-001 | SwRS-002 | `UserRightsConst.cs` (Zeilen 21-28, `[Obsolete]`) |
|
||||
| StRS-001 | SyRS-001 | SwRS-003 | `docs/guides/development/check-userrights.md` [SEKUNDÄR] |
|
||||
| StRS-002 | SyRS-002 | – | `CentronRights.md` Abschnitte 1.1/1.2 [SEKUNDÄR]; kein SwRS verifiziert [HYPOTHESE] |
|
||||
| StRS-003 | SyRS-003 | SwRS-005 | `ReceiptState.cs` |
|
||||
| StRS-003 | SyRS-004 | SwRS-004 | `ReceiptBase.cs` Zeile 65 |
|
||||
| StRS-004 | SyRS-005 | – | `receipts-backend-architecture.md` [SEKUNDÄR]; `AssetHeadDAO.SaveAssetVersion` nicht im Code gelesen [HYPOTHESE] |
|
||||
| StRS-005 | SyRS-006 | – | `WebReceiptOverview.razor` Zeile 1 (Token-Routing) |
|
||||
| StRS-005 | SyRS-007 | SwRS-006 | `WebReceiptState.cs` |
|
||||
| StRS-005 | SyRS-007 | SwRS-007 | `ReceiptBL.cs` Zeilen 6202-6243 |
|
||||
| StRS-005 | SyRS-007 | SwRS-008 | `ReceiptBL.cs` Zeilen 6226-6242 |
|
||||
| StRS-005 | SyRS-007 | SwRS-009 | `ReceiptBL.cs` Zeilen 6202-6207 |
|
||||
| StRS-006 | SyRS-008 | SwRS-010 | `ReceiptBL.cs` Zeilen 6290-6300 |
|
||||
| StRS-006 | SyRS-008 | SwRS-011 | `ReceiptBL.cs` Zeile 6287 |
|
||||
| StRS-006 | SyRS-008 | SwRS-012 | `SharedDocumentSignPage.razor` Zeilen 84-127 |
|
||||
| StRS-007 | SyRS-008 | SwRS-010 | `ReceiptBL.cs` Zeilen 6263-6264, `ReceiptPdfDocument.cs` Zeile 39 |
|
||||
| StRS-008 | SyRS-009 | SwRS-013 | `ReceiptContract.cs` (Existenz); `contracts-backend.md` [SEKUNDÄR] |
|
||||
| StRS-008 | SyRS-010 | SwRS-014 | `contracts-backend.md` Abschnitt „Payment and Collection“ [SEKUNDÄR/HYPOTHESE] |
|
||||
| StRS-009 | SyRS-010 | – | `contracts-backend.md` [SEKUNDÄR]; Berechnungslogik [HYPOTHESE] |
|
||||
| StRS-010 | SyRS-011 | SwRS-015 | `TimerBillingSettingsPageViewModel.cs` (Commit baa9e7bd9b) |
|
||||
| StRS-010 | SyRS-011 | SwRS-016 | `TimerBillingSettingsPageViewModel.cs` (Commit baa9e7bd9b) |
|
||||
| StRS-011 | SyRS-012 | SwRS-017 | `HelpdeskStatusBL.cs` Zeilen 40-50, 52-73 |
|
||||
| StRS-012 | SyRS-012 | SwRS-018 | `HelpdeskStatusBL.cs` Zeilen 75-104 |
|
||||
| StRS-013 | SyRS-013 | SwRS-019 | `SupplierEdiBL.cs` Zeile 1364 + Dateisystem |
|
||||
| StRS-014 | SyRS-013/014 | – | `edi-architecture.md` Tabelle „Document Types Supported“ [SEKUNDÄR/HYPOTHESE] |
|
||||
| StRS-015 | SyRS-015 | SwRS-020 | `OpenIdConnectAuthenticator.cs` Zeilen 14-23 |
|
||||
| StRS-015 | SyRS-015 | SwRS-021 | `OpenIdConnectAuthenticator.cs` Zeilen 39-63 |
|
||||
| StRS-015 | SyRS-016 | SwRS-020 | `OpenIdConnectAuthenticator.cs` Zeilen 17, 21, 61-62 |
|
||||
| StRS-015 | SyRS-017 | SwRS-022 | `TicketBL.cs` Zeilen 113-133 |
|
||||
| StRS-015 | SyRS-017 | SwRS-023 | `TicketBL.cs` Zeilen 136-163 |
|
||||
| StRS-016 | – | – | `LicenseManager.cs` Zeilen 243, 332 (SyRS-Verfeinerung in dieser Iteration nicht explizit als Einzel-SyRS geführt; siehe Analysebericht.md, Konsolidierungshinweis) |
|
||||
| StRS-017 | SyRS-018 | SwRS-024 | Commit `8dd17c7d1244c02ef57ee3f94a42249a056c74cd` [KONTEXT] |
|
||||
|
||||
## StRS/SyRS ohne eigene SwRS-Verfeinerung (bewusste Grenze der Analysetiefe)
|
||||
|
||||
| StRS-ID | SyRS-ID | Begründung für fehlende SwRS-Verfeinerung |
|
||||
|---|---|---|
|
||||
| StRS-002 | SyRS-002 | Konkrete Filterimplementierung (Query-Ebene) wurde nicht im Code lokalisiert; als `[HYPOTHESE]` in SyRS-002 offen dokumentiert. |
|
||||
| StRS-004 | SyRS-005 | `AssetHeadDAO.SaveAssetVersion` wurde nur über Dokumentation, nicht im Quellcode analysiert. |
|
||||
| StRS-009 | SyRS-010 | Kontingent-Berechnungsformel (`ContractContingentBalanceCalculation`) nicht im Code verifiziert. |
|
||||
| StRS-014 | SyRS-013, SyRS-014 | Lieferantenspezifische Dokumenttyp-Abdeckung nur dokumentarisch, nicht per Dateivergleich verifiziert. |
|
||||
| StRS-016 | – | Lizenz-Laufzeitprüfung ist in SwRS über SyRS-015 (StRS-015-Zweig) faktisch mitabgedeckt (`LicenseManager.HasLicense` wird sowohl für OIDC als auch generisch verwendet); keine eigenständige SyRS-Zeile für StRS-016 geführt – siehe Konsolidierungshinweis unten. |
|
||||
| – | SyRS-019 | Rein systemseitige NFR-Anforderung (Debug-Mailschutz) ohne StRS-Gegenstück, da sie kein Stakeholder-Ziel, sondern eine interne Entwicklungs-Schutzmaßnahme abbildet; bewusst dennoch aufgenommen (Sicherheitsrelevanz). |
|
||||
|
||||
## Bekannte Konsolidierungs-/Struktur-Hinweise aus der Traceability
|
||||
|
||||
- **StRS-016** (Lizenzierung allgemein) und **StRS-015** (OIDC-Login) teilen sich denselben technischen Mechanismus (`LicenseManager.HasLicense`). Im Zielsystem sollte die Lizenzprüfung als ein einziger SyRS-Anforderungsblock geführt werden, der beide StRS-Anforderungen bedient, statt lizenzspezifische Prüfungen pro Feature separat zu beschreiben.
|
||||
- **StRS-006/StRS-007** (Signatur erzwingen vs. Signatur überspringen) sind zwei Ausprägungen *eines* fachlichen Vorgangs („Auftrag aus Web-Angebot erzeugen“), aber als zwei StRS-Einträge geführt, weil der Code sie als zwei getrennte Methoden (`AcceptWebReceipt` / `AcceptWebReceiptWithoutSignature`) statt eines parametrisierten Ablaufs implementiert (siehe SwRS-010, Konsolidierungsfeld in StRS-007).
|
||||
|
||||
*Hinweis zur Prüfmethodik:* Alle in dieser Tabelle referenzierten IDs wurden gegen die tatsächlich in StRS.md/SyRS.md/SwRS.md vergebenen IDs abgeglichen (siehe Konsistenzcheck in [Analysebericht.md](Analysebericht.md)); ursprünglich fehlerhafte Querverweise (z. B. auf nicht existierende SwRS-Nummern) wurden vor Abgabe korrigiert.
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
# Messprotokoll – V1 (Baseline, solo) – Prompt-Version 01, Lauf 9 (Lauf C)
|
||||
|
||||
> V1-Messung im Agentenmodus `solo`. Teil eines Dreier-Parallelblocks (Läufe C, D, E), der die
|
||||
> V1-Reihe von zwei auf fünf Messpunkte bringt.
|
||||
>
|
||||
> **Parallelbetrieb:** Dieser Lauf lief zeitgleich mit `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180417_v3.3.0-664e`
|
||||
> und `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180418_v3.3.0-b676`. Drei Läufe konkurrierten um CPU, Netzwerk und
|
||||
> API-Kontingent. **Wanduhrzeit, `duration_ms` und `duration_api_ms` sind dadurch verzerrt**
|
||||
> und nicht mit seriellen Läufen vergleichbar. Tokens, Kosten, 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-25T18:04:32.5386788+02:00
|
||||
- **Endzeit:** 2026-08-25T18:21:59.4588888+02:00
|
||||
- **Dauer gesamt:** 00:17:27 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:17:25 (`duration_ms`) — API: 00:16:31
|
||||
- **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.3.0-5851`
|
||||
- **Ablage:** `Iteration 1/claude-sonnet-5/solo/high/`
|
||||
- **Parallele Läufe:** ja – `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180417_v3.3.0-664e`, `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180418_v3.3.0-b676`
|
||||
- **Skill-Version:** `3.3.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` — **nicht zur Laufzeit gesetzt**, sondern aus der Sitzung geerbt und
|
||||
nachträglich aus dem Session-Transkript rekonstruiert (111 Nachrichten, durchgängig `high`).
|
||||
`RawResult.json` enthält kein `effort`-Feld. Ab Skill-Version 3.4.0 wird der Wert per
|
||||
`--effort` explizit gesetzt.
|
||||
- **Modell:** `claude-sonnet-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
|
||||
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/20 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)
|
||||
- **Fast-Mode:** aus
|
||||
|
||||
## Verbrauch
|
||||
|
||||
### Hauptagent (`usage`)
|
||||
| Messgröße | Wert |
|
||||
|---|---|
|
||||
| Input-Tokens | 78 |
|
||||
| Output-Tokens | 95.127 (davon 14.407 Thinking-Tokens) |
|
||||
| Cache-Write-Tokens | 209.603 |
|
||||
| Cache-Read-Tokens | 5.350.672 |
|
||||
| Agent-Turns | 72 |
|
||||
|
||||
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
|
||||
| Messgröße | `claude-sonnet-5` | `claude-haiku-4-5-20251001` | Summe |
|
||||
|---|---:|---:|---:|
|
||||
| Input-Tokens | 78 | 4.192 | 4.270 |
|
||||
| Output-Tokens | 95.127 | 20 | 95.147 |
|
||||
| Cache-Write-Tokens | 209.603 | 0 | 209.603 |
|
||||
| Cache-Read-Tokens | 5.350.672 | 0 | 5.350.672 |
|
||||
| Tokens gesamt | 5.655.480 | 4.212 | **5.659.692** |
|
||||
|
||||
**Tokens gesamt: 5.659.692** (Summe aus Input, Output, Cache-Write und Cache-Read ueber alle Modelle; `total_cost_usd` steht weiterhin in `RawResult.json`)
|
||||
|
||||
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-sonnet-5` identisch.
|
||||
|
||||
## Ergebnis
|
||||
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
|
||||
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
|
||||
- **Session-ID:** `d17a0f5e-a2fe-4b27-a48b-53d1997b2b8b`
|
||||
- **Permission-Denials:** **0** – auch keine auf `Task`/`Agent`/`Workflow`
|
||||
- **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` | 32.868 B | 17 Anforderungen |
|
||||
| `SyRS.md` | 32.688 B | 19 Anforderungen |
|
||||
| `SwRS.md` | 37.149 B | 24 Anforderungen |
|
||||
| `Traceability.md` | 5.685 B | 39 Datenzeilen |
|
||||
| `Hypothesen.md` | 4.874 B | Sammlung der `[HYPOTHESE]`-Aussagen |
|
||||
| `Glossar.md` | 7.259 B | Domänenbegriffe |
|
||||
| `Analysebericht.md` | 14.546 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
|
||||
|
||||
Summe: **60 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`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 17 | 28,3 % |
|
||||
| SyRS | 19 | 31,7 % |
|
||||
| SwRS | 24 | 40,0 % |
|
||||
| **Gesamt** | **60** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 28 | 46,7 % |
|
||||
| Sicherheit | 13 | 21,7 % |
|
||||
| Daten | 11 | 18,3 % |
|
||||
| nicht-funktional | 2 | 3,3 % |
|
||||
| Schnittstelle | 1 | 1,7 % |
|
||||
| Zuverlässigkeit | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Benutzbarkeit – Erkennbarkeit der Bedienung) | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Sicherheit – Vertraulichkeit/Schutz vor Fehlbedienung) | 1 | 1,7 % |
|
||||
| Performance-Effizienz | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Benutzbarkeit) | 1 | 1,7 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 82 |
|
||||
| davon `PRIMÄR` | 51 (62,2 %) |
|
||||
| davon `SEKUNDÄR` | 24 (29,3 %) |
|
||||
| davon `KONTEXT` | 7 (8,5 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 45 (75,0 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 45 | 75,0 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 15 | 25,0 % |
|
||||
| als Workaround vermerkt | 10 | 16,7 % |
|
||||
| Konsolidierungskandidaten | 2 | 3,3 % |
|
||||
| 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]` | **verletzt** – 1 von 26 ungedeckt: SwRS-003 |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 59 von 60 mit Tracelinks (98,3 %) |
|
||||
|
||||
## V1-Reihe: fünf Messpunkte unter identischer Bedingung
|
||||
|
||||
| | Lauf A | Lauf B | **Lauf C** | **Lauf D** | **Lauf E** |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| Anforderungen | 42 | 82 | **60** | **73** | **67** |
|
||||
| — StRS/SyRS/SwRS | 14/15/13 | 20/34/28 | **17/19/24** | **18/24/31** | **19/20/28** |
|
||||
| Tokens gesamt | 4.357.855 | 12.598.503 | **5.659.692** | **4.591.733** | **5.050.595** |
|
||||
| Output-Tokens | 70.749 | 129.077 | **95.147** | **103.814** | **89.793** |
|
||||
| Thinking-Tokens | 10.470 | 21.863 | **14.407** | **22.957** | **11.962** |
|
||||
| Cache-Read | 4,12 M | 12,23 M | **5,35 M** | **4,33 M** | **4,73 M** |
|
||||
| Agent-Turns | 68 | 107 | **72** | **77** | **67** |
|
||||
| Traceability-Zeilen | 19 | 36 | **39** | **33** | **31** |
|
||||
| Denials / Subagenten | 0 / 0 | 0 / 0 | **0 / 0** | **0 / 0** | **0 / 0** |
|
||||
|
||||
**V1 gesamt:** Anforderungen 42–82 (Median 67), Tokens 4.357.855–12.598.503 (Median 5.050.595).
|
||||
|
||||
## Vergleich V1 (solo) gegen V1b (builtin)
|
||||
|
||||
| | V1 (5 Läufe) | V1b (4 vollständige Läufe) |
|
||||
|---|---|---|
|
||||
| Anforderungen | 42 – 82 (Faktor **2,0**) | 55 – 325 (Faktor **5,9**) |
|
||||
| Tokens gesamt | 4.357.855 – 12.598.503 (Faktor **2,9**) | 11.516.200 – 52.713.542 (Faktor **4,6**) |
|
||||
| Median Tokens | **5.050.595** | **30.065.183** |
|
||||
| Subagenten | 0 (erzwungen) | 0 – 14 (selbstgewählt) |
|
||||
|
||||
## Anmerkungen/Auffälligkeiten
|
||||
|
||||
1. **V1 ist deutlich stabiler als V1b.** Die drei parallelen Läufe C, D und E liegen bei 60, 73
|
||||
und 67 Anforderungen und 2,86, 2,54 und 5.050.595 Tokens – eine Spanne von nur ±11 % bzw. ±6 %.
|
||||
Über alle fünf V1-Läufe beträgt die Streuung Faktor 2,0 (Anforderungen) und 2,9 (Tokens),
|
||||
gegenüber Faktor 5,9 und 4,6 in V1b. **Die selbstgewählte Zerlegung in Subagenten ist damit
|
||||
als Hauptursache der V1b-Streuung bestätigt:** Wird sie unterbunden, schrumpft die Streuung
|
||||
auf weniger als die Hälfte.
|
||||
|
||||
2. **V1 kostet ein Vielfaches weniger.** Median 5.050.595 Tokens gegenüber 30.065.183 in V1b, und
|
||||
selbst der teuerste V1-Lauf (12.598.503 Tokens) liegt unter dem günstigsten V1b-Lauf (11.516.200 Tokens).
|
||||
Ursache sind die deutlich niedrigeren Cache-Read-Tokens: 4,1 bis 12,2 Mio. gegenüber 10,5 bis
|
||||
44,8 Mio. Ohne parallele Kontexte entfällt das mehrfache Einlesen derselben Artefakte.
|
||||
|
||||
3. **Lauf B bleibt der Ausreißer der V1-Reihe.** Mit 82 Anforderungen, 12.598.503 Tokens und 12,23 Mio.
|
||||
Cache-Reads liegt er deutlich über den vier übrigen V1-Läufen, die eng zwischen 42 und 73
|
||||
bzw. 2,20 und 5.659.692 Tokens liegen. Bei fünf Messpunkten ist das noch nicht als Ausreißer im
|
||||
statistischen Sinn zu behandeln, aber als Beobachtung festzuhalten.
|
||||
|
||||
4. **Effort war durchgängig `high`** – für alle drei Läufe aus den Transkripten belegt
|
||||
(95 bis 117 Nachrichten je Lauf). Der Denkaufwand scheidet damit als Erklärung für
|
||||
verbleibende Unterschiede innerhalb der V1-Reihe aus.
|
||||
|
||||
5. **Dreifachparallelität technisch fehlerfrei.** Alle drei Läufe schrieben in getrennte
|
||||
Verzeichnisse mit eigenem `_meta`. Keine Kollision, keine gegenseitige Überschreibung, alle
|
||||
drei Ergebnisverzeichnisse frei von Fremddateien, Root unverändert. Das Verfahren aus
|
||||
Skill-Version 3.1.0 skaliert auch über zwei gleichzeitige Läufe hinaus.
|
||||
|
||||
6. **Wanduhrzeiten nicht auswerten.** Alle drei Läufe brauchten 16:29 bis 17:49 – bei drei
|
||||
konkurrierenden Prozessen auf einer Maschine ist das kein inhaltliches Signal. Für
|
||||
Laufzeitvergleiche seriell messen.
|
||||
|
||||
7. **Manuelle Eingriffe während des Laufs:** keine.
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"is_error":false,"duration_api_ms":990994,"num_turns":72,"stop_reason":"end_turn","session_id":"d17a0f5e-a2fe-4b27-a48b-53d1997b2b8b","total_cost_usd":2.8642644,"usage":{"input_tokens":78,"cache_creation_input_tokens":209603,"cache_read_input_tokens":5350672,"output_tokens":95127,"output_tokens_details":{"thinking_tokens":14407},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":209603,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":561,"cache_read_input_tokens":236333,"cache_creation_input_tokens":993,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":993},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":20,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004292000000000001,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-sonnet-5":{"inputTokens":78,"outputTokens":95127,"cacheReadInputTokens":5350672,"cacheCreationInputTokens":209603,"webSearchRequests":0,"costUSD":2.8599724,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-sonnet-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":"All seven deliverables are in place and clean (the only remaining mentions of the invalid IDs are the deliberate historical note in the consistency-check section of the Analysebericht). The specification is complete:\n\n- **StRS.md** — 17 stakeholder requirements across 9 domains (rights, receipts, WebOffer/C-Sign, contracts, timer billing, helpdesk, EDI, auth/licensing, ribbon UX)\n- **SyRS.md** — 19 system requirements\n- **SwRS.md** — 24 software/component requirements\n- **Traceability.md** — consolidated StRS↔SyRS↔SwRS matrix with documented gaps\n- **Hypothesen.md** — 10 open `[HYPOTHESE]` items with concrete follow-up questions\n- **Glossar.md** — domain terminology\n- **Analysebericht.md** — scope/depth per module, consistency check (no duplicate IDs, no un-evidenced requirements, 5 broken tracelinks found and fixed), and self-assessment with concrete follow-up recommendations\n\nAll 60 requirements carry at least one classified evidence item (PRIMÄR/SEKUNDÄR/KONTEXT) tied to actual file paths/line numbers or commits I verified in the codebase, and every security/billing/rights requirement without a PRIMÄR-grade beleg is explicitly flagged as `[HYPOTHESE]` per the risk-based rule. Given the codebase's size (~16k C# files), this run deliberately went deep on 9 representative domains rather than shallow across everything — that scoping decision and its gaps are documented transparently in Analysebericht.md §2 and §4.","ttft_ms":4996,"ttft_stream_ms":1566,"time_to_request_ms":40,"type":"result","duration_ms":1045082,"uuid":"edd34e23-123d-4a0f-ac72-2f5ce685d4a1","queued_turn_count":0}
|
||||
+1044
File diff suppressed because it is too large
Load Diff
+65
@@ -0,0 +1,65 @@
|
||||
## Gefundene Anforderungen
|
||||
|
||||
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 17 | 28,3 % |
|
||||
| SyRS | 19 | 31,7 % |
|
||||
| SwRS | 24 | 40,0 % |
|
||||
| **Gesamt** | **60** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 28 | 46,7 % |
|
||||
| Sicherheit | 13 | 21,7 % |
|
||||
| Daten | 11 | 18,3 % |
|
||||
| nicht-funktional | 2 | 3,3 % |
|
||||
| Schnittstelle | 1 | 1,7 % |
|
||||
| Zuverlässigkeit | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Benutzbarkeit – Erkennbarkeit der Bedienung) | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Sicherheit – Vertraulichkeit/Schutz vor Fehlbedienung) | 1 | 1,7 % |
|
||||
| Performance-Effizienz | 1 | 1,7 % |
|
||||
| nicht-funktional (ISO/IEC 25010: Benutzbarkeit) | 1 | 1,7 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 82 |
|
||||
| davon `PRIMÄR` | 51 (62,2 %) |
|
||||
| davon `SEKUNDÄR` | 24 (29,3 %) |
|
||||
| davon `KONTEXT` | 7 (8,5 %) |
|
||||
| Belege je Anforderung (Median) | 1,0 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 45 (75,0 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 45 | 75,0 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 15 | 25,0 % |
|
||||
| als Workaround vermerkt | 10 | 16,7 % |
|
||||
| Konsolidierungskandidaten | 2 | 3,3 % |
|
||||
| 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]` | **verletzt** – 1 von 26 ungedeckt: SwRS-003 |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 59 von 60 mit Tracelinks (98,3 %) |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+132
@@ -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_180416_sonnet5_solo_v3.3.0-5851\Ergebnisse\`.
|
||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:21:59.4588888+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:04:32.5386788+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# Subagenten-Aufrufe
|
||||
|
||||
Session `d17a0f5e-a2fe-4b27-a48b-53d1997b2b8b`, Transkript `d17a0f5e-a2fe-4b27-a48b-53d1997b2b8b.jsonl`.
|
||||
|
||||
`subagent_stats`: **0** Subagenten gesamt, davon **0** von Subagenten gestartet (max_depth 0). Direkt vom Hauptagenten erwartet: **0**. Im Transkript gefunden: **0**.
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
# Analysebericht — Reverse Requirements Engineering c-entron ERP
|
||||
|
||||
Iteration 01 (Initial-Prompt), Versuch V1 Baseline (Prompt-only). Erstellt ohne spezialisierte Agenten oder MCP-Server, ausschließlich auf Basis der im Arbeitsverzeichnis lesbaren Artefakte (statische Analyse, keine Ausführung).
|
||||
|
||||
## 1. Umfang der Codebasis (Ausgangslage)
|
||||
|
||||
Die Codebasis `CentronERP` ist eine vollständige ERP-Suite mit folgender grober Größenordnung (per Dateizählung ermittelt):
|
||||
|
||||
- ca. 15.554 C#-Dateien, davon 1.185 allein in `Centron.Entities` (Datenmodell) und 2.068 in `Centron.BL` (Businesslogik, verteilt auf **ca. 85 fachliche Unterordner** wie Sales, Finances, Warehousing, Security, Purchasing, Projects, TicketProjects, VideoPortal, ItPlanner u. v. m.)
|
||||
- ca. 1.233 XAML-Dateien (WPF-Desktop-Oberfläche, `Centron.WPF.UI`)
|
||||
- Zusätzliche Teilsysteme: Web-API (`Centron.Controllers`/`Centron.Host`), Outlook-Add-in, Nexus-Ticketsystem (Blazor), diverse externe API-Anbindungen (GLS, Shipcloud, ITscope, Icecat, FinAPI, EGIS/EDI, eBInterface)
|
||||
- Keine `.sql`-Migrationsdateien außerhalb von Build-Output (`bin`/`obj`) im Repository auffindbar; das DB-Schema selbst liegt nicht als durchsuchbare Datei vor — alle DB-Strukturaussagen (Tabellen-/Spaltennamen) stützen sich auf im Anwendungscode eingebettetes SQL bzw. NHibernate-Mappings.
|
||||
|
||||
**Konsequenz für diese Iteration:** Eine erschöpfende Einzelanalyse aller Module in vergleichbarer Tiefe war im Rahmen eines einzelnen Analyselaufs nicht leistbar. Es wurde daher — wie im Auftrag vorgesehen — eine selbstständige Priorisierung vorgenommen (siehe Abschnitt 2) und diese Entscheidung hier transparent dokumentiert.
|
||||
|
||||
## 2. Priorisierung der Analysetiefe
|
||||
|
||||
### 2.1 Tief analysiert (Code gelesen, Requirements mit PRIMÄR-Beleg abgeleitet)
|
||||
|
||||
| Bereich | Repräsentative Dateien | Anzahl Requirements |
|
||||
|---|---|---|
|
||||
| Beleg-Versionierung (Angebot/Auftrag/Lieferschein/Rechnung/Gutschrift/Vertrag) | `AssetBL.cs`, `AssetBase.cs`, `CustomerAssetBL.cs` | StRS-01, StRS-15; SyRS-01/02/21; SwRS-01/02/03/28 |
|
||||
| Rechnungsstorno & Belegstatus | `InvoiceBL.cs`, `StateToStringConverter.cs` | StRS-02, StRS-16; SyRS-03/04/22; SwRS-04/05/29 |
|
||||
| Automatische/Vertragliche Fakturierung | `AutomaticFacturaBL.cs`, `ContractBL.cs` | StRS-03, StRS-04; SyRS-05/06; SwRS-06/07/08 |
|
||||
| TimerBilling-Einstellungen | `TimerBillingSettingsPageViewModel.cs` (+ Commit baa9e7bd9b) | StRS-05; SyRS-07/08; SwRS-09/10 |
|
||||
| Internes Rechtemodell (Gruppen/Sichtrus/Sichmemb) | `AppRightsBL.cs`, `UserRightsExt.cs`, `UserRightsConst.cs` | StRS-06, StRS-07; SyRS-09/10/11; SwRS-11/12/13/14/15 |
|
||||
| Web-Rechte & Portal-Datenisolation | `AppRightsBL.cs` (Web-Teile), `InvoiceBL.GetInvoiceByFilter` | StRS-08, StRS-09; SyRS-12/13; SwRS-16/17/18/19 |
|
||||
| Zwei-Faktor-Authentifizierung | `TwoFactorAuthenticationBL.cs` | StRS-10; SyRS-14; SwRS-20/21 |
|
||||
| Digitale PDF-Signatur / Verschlüsselung | `PdfSigningBL.cs` | StRS-11, StRS-18; SyRS-15/16/17; SwRS-22/23/24 |
|
||||
| Ticket-/Helpdesk-Status & Sichtbarkeit | `HelpdeskState.cs`, `ShowHelpdeskRight.cs` | StRS-12, StRS-13; SyRS-18/19; SwRS-25/26 |
|
||||
| Artikel-Bestandsführung | `ArticleBL.cs` (SQL-Fragment) | StRS-14; SyRS-20; SwRS-27 |
|
||||
| Web-API-Autorisierung | `AuthorizeUserRightAttribute.cs`, `AuthorizeAnyUserRightAttribute.cs`, `AuthorizeAllUserRightsAttribute.cs` | StRS-17; SyRS-23/24; SwRS-30/31 |
|
||||
|
||||
Diese Auswahl deckt bewusst mehrere Anforderungstypen ab (funktional, Sicherheit, Daten, nicht-funktional) sowie die vom Auftrag als besonders evidenzkritisch benannten Bereiche (Sicherheit, Abrechnung/Fakturierung, Berechtigungen).
|
||||
|
||||
### 2.2 Stichprobenhaft betrachtet (Verzeichnisstruktur/Signaturen gesichtet, kein Volltext gelesen)
|
||||
|
||||
- Struktur von `Centron.BL/Sales` (248 Dateien: Customers, CRM, Marketing, HourlySurchargeRates, CashBooks, DocumentationWizardArea)
|
||||
- Struktur von `Centron.BL/Warehousing` (40 Dateien: ArticleUnit, Barcode, CostCenter, Tax)
|
||||
- `BusinessPartner`-Modul (`SupplierAssetBL.cs`, `SearchSupplierBL.cs`) — nur Dateiliste, kein Code gelesen
|
||||
- Fünf weitere Beleg-BL-Klassen (`OfferBL`, `OrderBL`, `ContractBL`, `CreditVoucherBL`, `DeliveryListBL`) bzgl. `IsWebAccountLogin`-Musters — nur Grep-Treffer, siehe Hypothesen.md H-06
|
||||
- `IsAdmin()`-Verwendungsstellen in `DocumentationBL.cs`, `CampaignBL.cs` — nur Fundstellenliste, siehe Hypothesen.md H-07
|
||||
- `ChangeTracking`-Modul (nur 1 Datei: `ImportHistoryBL.cs`) — Struktur gesichtet, Inhalt nicht gelesen
|
||||
|
||||
### 2.3 Nicht analysiert (nur Existenz/Ordnername bekannt)
|
||||
|
||||
Die überwiegende Mehrheit der Codebasis wurde in dieser Iteration **nicht** inhaltlich gesichtet, u. a.:
|
||||
|
||||
- Ca. 70+ weitere BL-Unterordner: Accounts, Buying, Calendar, Chats, DocuBoard, EDI, ExternalHelpdesk, ItPlanner, MailScanner, Mobile, Production, ProductMatrix, Projects, Reporting, RiverDivo, SelfCare, SocialMedia, Statistics, TaskManager, Tapi, TradePool, VideoPortal, WebSuite u. v. m.
|
||||
- Gesamte WPF-UI-Schicht (`Centron.WPF.UI`, 1.233 XAML-Dateien) außer den beiden explizit zitierten Fundstellen
|
||||
- Gesamte API-Controller-Schicht (`Centron.Controllers/Controllers/v1`) außer den drei Autorisierungs-Attributen
|
||||
- Nexus-Ticketsystem (`src/nexus`, Blazor-basiert) inhaltlich
|
||||
- Alle externen Schnittstellenmodule (`src/apis/*`: GLS, Shipcloud, ITscope, Icecat, FinAPI, EGIS, eBInterface)
|
||||
- Deployment-/Docker-/Build-Konfiguration (`deployment/`, `docker/`, `azure/`)
|
||||
- Alle Testprojekte (`tests/*`) — nicht als Anforderungsquelle herangezogen, obwohl Tests potenziell wertvolle Belege für erwartetes Verhalten liefern könnten
|
||||
- Vollständiges Datenbankschema (keine `.sql`-Dateien im Repository gefunden; DB-Struktur nur indirekt über eingebettetes SQL erschlossen)
|
||||
|
||||
**Diese Lücke ist die zentrale Einschränkung dieser Iteration** und sollte in Abschnitt 5 (Empfehlungen) berücksichtigt werden.
|
||||
|
||||
## 3. Ergebnisumfang dieser Iteration
|
||||
|
||||
| Dokument | Anzahl Einträge |
|
||||
|---|---|
|
||||
| StRS.md | 18 Anforderungen |
|
||||
| SyRS.md | 24 Anforderungen |
|
||||
| SwRS.md | 31 Anforderungen |
|
||||
| Traceability.md | 31 Zeilen (StRS×SyRS×SwRS-Tripel, inkl. einer Mehrfachverwendung SwRS-24) |
|
||||
| Hypothesen.md | 7 offene Hypothesen (H-01 bis H-07) |
|
||||
| Glossar.md | 28 Begriffe |
|
||||
|
||||
Belegklassifikation über alle 73 Anforderungen (StRS+SyRS+SwRS): **PRIMÄR dominiert** — jede sicherheits- und fakturierungsrelevante Anforderung (StRS-02, -06 bis -11, -16 bis -18 sowie zugehörige SyRS/SwRS) trägt mindestens einen PRIMÄR-Beleg, wie vom Auftrag für diese Kategorien zwingend gefordert. Rein SEKUNDÄR/KONTEXT-gestützte Aussagen sind auf zwei Stellen konzentriert (StRS-02/SyRS-04 Belegstatus-Wertebereich; SwRS-19 fünf ungeprüfte Beleg-BL-Dateien) und jeweils in Hypothesen.md verzeichnet.
|
||||
|
||||
## 4. Konsistenzcheck
|
||||
|
||||
Automatisiert (Textsuche) über StRS.md, SyRS.md, SwRS.md, Traceability.md durchgeführt:
|
||||
|
||||
- **Doppelte/mehrfach vergebene IDs:** Keine gefunden. StRS-01…18, SyRS-01…24, SwRS-01…31 kommen jeweils genau einmal als `ID:`-Zeile vor.
|
||||
- **Anforderungen ohne Beleg:** Keine gefunden. Jede der 73 Anforderungen enthält mindestens eine `Belege:`-Zeile mit mindestens einem klassifizierten Eintrag (PRIMÄR/SEKUNDÄR/KONTEXT).
|
||||
- **Tracelinks auf nicht existierende IDs:** Keine gefunden. Alle in StRS.md referenzierten SyRS-IDs (SyRS-01…24) existieren in SyRS.md; alle in SyRS.md referenzierten StRS-IDs existieren in StRS.md; alle in SwRS.md referenzierten SyRS-IDs existieren in SyRS.md.
|
||||
- **Korrektur während der Erstellung:** Eine Inkonsistenz wurde gefunden und behoben — StRS-01 referenzierte ursprünglich nur SyRS-01, obwohl auch SyRS-02 als Kind-Anforderung auf StRS-01 zurückverweist; StRS-01 wurde um den Tracelink zu SyRS-02 ergänzt.
|
||||
|
||||
## 5. Selbstbewertung
|
||||
|
||||
**Vollständig analysiert:** Kein Modul im Sinne von „jede Datei gelesen“; auch die tief analysierten Bereiche (Abschnitt 2.1) sind jeweils nur mit 1–5 Dateien pro Thema exemplarisch belegt, nicht vollständig durchdrungen (z. B. wurde von `ArticleBL.cs`, ca. 3.600+ Zeilen, nur ein einzelnes SQL-Fragment gelesen).
|
||||
|
||||
**Nur stichprobenhaft analysiert:** Sales-Gesamtmodul (248 Dateien, nur Verzeichnisstruktur + 6 Kern-BL-Klassen inhaltlich), Warehousing-Gesamtmodul (40 Dateien, nur 1 SQL-Fragment aus 1 Datei), BusinessPartner-Modul.
|
||||
|
||||
**Gar nicht analysiert:** Ca. 70 der ca. 85 BL-Unterordner, die komplette WPF-UI-Schicht bis auf 2 Fundstellen, das Nexus-Ticketsystem inhaltlich, alle externen API-Module, das tatsächliche DB-Schema, alle Testprojekte.
|
||||
|
||||
**Wo war der Beleg dünn?**
|
||||
- StRS-02/SyRS-04 (Belegstatus-Wertebereich): nur SEKUNDÄR (UI-Converter), kein DB-Constraint gefunden — siehe H-03.
|
||||
- SwRS-19 (WebAccount-Filterung in 5 weiteren Beleg-Klassen): nur SEKUNDÄR (Grep-Treffer), keine Einzelverifikation — siehe H-06.
|
||||
- StRS-13/SyRS-19/SwRS-26 (ShowHelpdeskRight): Enum-Definition PRIMÄR belegt, aber die tatsächliche Auswertungsstelle (wo/wie gefiltert wird) nicht gefunden — als [HYPOTHESE] gekennzeichnet, siehe H-02.
|
||||
- StRS-07 (Admin-Bypass): nur 2 von ca. 9 gefundenen `IsAdmin()`-Aufrufstellen inhaltlich geprüft — siehe H-07.
|
||||
|
||||
**Welche Erkenntnisse legen einen Nachschlag in einer Folge-Iteration nahe?**
|
||||
|
||||
1. **Modulweite Ausweitung:** Die in dieser Iteration identifizierten Muster (Beleg-Versionierung, Gruppenrechte, WebAccount-Isolation) sollten systematisch auf die übrigen fünf Beleg-BL-Klassen (Offer/Order/Contract/CreditVoucher/DeliveryList) angewendet und einzeln verifiziert werden (H-06), bevor sie als generelles Architekturprinzip in eine Zielsystem-Spezifikation übernommen werden.
|
||||
2. **Rechtemodell-Vertiefung:** Cache-Invalidierungsverhalten bei Rechteänderungen (H-05) ist sicherheitsrelevant und sollte vorrangig geklärt werden, da es die Wirksamkeit von Rechteentzug zur Laufzeit betrifft.
|
||||
3. **Admin-Bypass-Reichweite:** Vollständige Erhebung aller `IsAdmin()`-Aufrufstellen (H-01, H-07) wird für eine belastbare Sicherheitsanforderung im Zielsystem benötigt.
|
||||
4. **Fakturierung/Buchhaltung vertiefen:** Nur ein Bruchteil der Sales/Finances-Logik (Offers, DownPayment, PartialCommission, Provision, RMA — alle als Dateien identifiziert, nicht gelesen) wurde erfasst; angesichts der im Auftrag geforderten strengen Evidenzpflicht für Abrechnungslogik ist hier der größte verbleibende Analysebedarf zu vermuten.
|
||||
5. **DB-Schema separat beschaffen:** Da keine `.sql`-Dateien im Repository vorliegen, sollte eine Folge-Iteration gezielt versuchen, das tatsächliche Datenbankschema (z. B. über ein separates Schema-Dump-Artefakt) einzubeziehen, um DB-Constraints von reiner Code-/UI-Konvention zu unterscheiden (betrifft insb. H-03).
|
||||
6. **Konsolidierungspotenzial:** Die drei nahezu identischen API-Autorisierungs-Attribute (StRS-17/SyRS-23/24) sowie das sechsfach duplizierte WebAccount-Filtermuster (StRS-09) sind bereits als Konsolidierungskandidaten markiert und sollten in einer Zielarchitektur zusammengeführt werden.
|
||||
7. **Ticket-/Nexus-Bereich:** Trotz aktiver Entwicklungstätigkeit in der Commit-Historie (Ticket-Caching, Teams-Integration, Forwarding-Dialoge) wurde das Nexus-Ticketsystem in dieser Iteration nicht inhaltlich untersucht — hohes Potenzial für weitere StRS/SyRS/SwRS-Anforderungen.
|
||||
|
||||
## 6. Methodische Anmerkung zur Belegtiefe
|
||||
|
||||
Alle Zeilennummern-Angaben in den Belegen beziehen sich auf den Dateistand zum Zeitpunkt dieser Analyse (Commit `79c1142f48`, 2026-08-25) und können sich bei künftigen Änderungen verschieben. Wo eine Methode über den zitierten Ausschnitt hinausgeht, wurde dies nicht immer bis zum Dateiende geprüft; entsprechende Einschränkungen sind, wo bekannt, im Feld „Fakt“ oder als Hypothese vermerkt.
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
# Glossar — Domänenbegriffe
|
||||
|
||||
Begriffe, wie sie in StRS.md, SyRS.md und SwRS.md verwendet werden. Deutsche Fachbegriffe und deutsche Original-Datenbank-/Feldbezeichner (Legacy-Namensgebung) werden erklärt; technische Bezeichner (Klassen, Methoden) bleiben unübersetzt.
|
||||
|
||||
| Begriff | Erklärung |
|
||||
|---|---|
|
||||
| **Beleg / Kundenbeleg** | Sammelbegriff für die versionierten Geschäftsdokumente eines Kunden: Angebot (Offer), Auftrag (Order), Lieferschein (DeliveryList), Rechnung (Invoice), Gutschrift (CreditVoucher), Vertrag (Contract). Technisch abgeleitet von `AssetBase`/`CustomerAsset`. |
|
||||
| **Asset (im Code)** | Technischer Oberbegriff für einen Beleg in der Codebasis (`AssetBL<T,V>`, `CustomerAsset<V>`); nicht zu verwechseln mit „Anlagevermögen“. |
|
||||
| **Version / MaxVersion / OldVersion** | Ganzzahlige Felder, die die Versionsnummer eines Belegs führen. `Version` ist die aktuell gültige Version, `MaxVersion` die höchste je erreichte Version, `OldVersion` die vorherige Version vor einer Änderung. |
|
||||
| **State (Belegstatus)** | Ganzzahliges Statusfeld eines Belegs mit belegtem Wertebereich 1=offen, 2=abgeschlossen, 3=abgebrochen (siehe `StateToStringConverter`). |
|
||||
| **Storno / Stornierung** | Fachlicher Vorgang, eine Rechnung als ungültig zu markieren, ohne sie zu löschen; technisch realisiert als neue Version mit `State=3` und Positionsmenge 0 (`InvoiceBL.CancelInvoice`). |
|
||||
| **Sammelfakturierung / Automatische Factura** | Prozess, mehrere offene Lieferscheine/Aufträge eines Kunden zu einem Stichtag automatisiert zu einer Rechnung zusammenzufassen (`AutomaticFacturaBL`). |
|
||||
| **Vertrag / Contract** | Belegart für wiederkehrende Leistungsbeziehungen mit Laufzeit (`Beginn`, `LaufzeitArt`, `LaufzeitDauer`) und Abrechnungsintervall (`BillingIntervalKinds`). |
|
||||
| **ClickContract** | Spezialform eines Vertrags mit klickbasierter Abrechnung (z. B. Drucker-/Kopierer-Klickzähler), siehe `ClickContractAssetBL`, `DeviceClickCounterBL`. |
|
||||
| **TimerBilling** | Prozess, erfasste Arbeitszeiten (Ticket-Timer) zu einem Rechnungs- oder Lieferschein-Beleg zu verdichten. |
|
||||
| **Recht (User Right)** | Einzelne, über eine ganzzahlige ID identifizierte Berechtigung im internen Mitarbeiter-Rechtemodell, gespeichert in Tabelle `Sichtrus` (Recht↔Gruppe) und geprüft über `Sichmemb` (Benutzer↔Gruppe). |
|
||||
| **Sichtrus / Sichmemb** | Legacy-benannte Datenbanktabellen des internen Gruppenrechtemodells: `Sichtrus` verknüpft ein Recht (`Recht`) mit einer Gruppe (`Gruppe`), `Sichmemb` verknüpft einen Benutzer (`Benutzer`) mit einer Gruppe. Namensherkunft vermutlich „Sicht“ + „Rechte“/„Mitgliedschaft“, nicht abschließend verifiziert. |
|
||||
| **Gruppe (AppGroup)** | Organisationseinheit, der Rechte zugeordnet werden; Benutzer erben Rechte ausschließlich über Gruppenmitgliedschaft. |
|
||||
| **WebAccount** | Zugangskonto für das Kundenportal (externe Kunden), technisch getrennt vom internen `AppUser`. Besitzt eine eigene `CustomerI3D`-Zuordnung und ein eigenes Rechtemodell (`WebAccountsRights`). |
|
||||
| **WebAccountsRights** | Datenbanktabelle für Rechte von Kundenportal-Zugängen, unabhängig vom internen Sichtrus/Sichmemb-Modell. |
|
||||
| **I3D** | In der Codebasis durchgängig verwendetes Suffix/Präfix für Primärschlüssel-/Fremdschlüsselfelder (z. B. `CustomerI3D`, `AppUserI3D`). Vermutlich Legacy-Bezeichnung für einen internen Identity-/ID-Feldtyp; exakte Herkunft/Bedeutung des Kürzels nicht verifiziert. |
|
||||
| **TOTP / 2FA-Schlüssel** | Zeitbasiertes Einmalpasswort-Verfahren (Time-based One-Time Password); der geheime Schlüssel wird je Mitarbeiter in der Personalverwaltung hinterlegt und über `GoogleAuthenticator.TwoFactorAuthenticator` validiert. |
|
||||
| **TSA (Time-Stamp Authority)** | Externer Zeitstempeldienst, der einer digitalen PDF-Signatur einen vertrauenswürdigen Zeitpunkt hinzufügt (`PdfSigningBL`, `DevExpress.Office.Tsp`). |
|
||||
| **C-Sign** | Im Rahmen der Commit-Historie verwendete Produktbezeichnung für die Signatur-/Unterschriftsfunktion (u. a. Web-Angebotsannahme mit digitaler Unterschrift). |
|
||||
| **HelpdeskState** | Stammdatenentität für einen konfigurierbaren Ticketstatus (Icon, Farbe, Aktivierung, Verrechnungsrelevanz). |
|
||||
| **ShowHelpdeskRight** | Enum mit fünf Stufen der Ticket-Sichtbarkeit eines Benutzers: `None`, `OnlyOwn`, `OnlyOwnAndNotify`, `All`, `OnlyOwnBranch`. |
|
||||
| **BarcodeScanen** | Boolesches Artikel-Flag, das bestimmt, ob der Bestand über Barcode-/Seriennummernzählung (`cfn_BarcodeCount`) oder über Mengenbestand (`NebenlagerArtikel.Bestand`) ermittelt wird. |
|
||||
| **Nebenlager / NebenlagerArtikel** | Zusätzliches Lager (Nebenlager) neben dem Hauptlager; `NebenlagerArtikel.Bestand` führt die dort verfügbare Menge je Artikel. |
|
||||
| **Bestand** | Deutsches Feld für die verfügbare Lagermenge eines Artikels. |
|
||||
| **CustomerFinanceInfo** | Aggregiertes Datenobjekt mit kundenspezifischen Finanzkonditionen (Rabatt, Zahlungsbedingung, USt-Befreiung), das bei Belegneuanlage in den Belegkopf übernommen wird. |
|
||||
| **AppSettingsConst / Application Setting** | Zentral in der Datenbank abgelegte, global (mandantenweit) gültige Konfigurationswerte (z. B. `InvoiceReminderDays`, `PdfSigningTsaServerUrl`). |
|
||||
| **CentronCache** | Anwendungsweiter In-Memory-Cache für u. a. `ReceiptSettings`, aus dem UI-ViewModels Konfigurationswerte ohne erneuten Serverzugriff lesen. |
|
||||
| **CentronObjectKindNumeric** | Enum, das die verschiedenen Belegarten (u. a. `OfferClass`, `OrderClass`, `InvoiceClass`, `DeliveryListClass`, `CreditVoucherClass`) numerisch kodiert. |
|
||||
| **NamedQuery** | Vordefinierte, im Mapping hinterlegte Datenbankabfrage (Gegensatz zu dynamisch/roh erzeugtem SQL), referenziert über `NamedQueryEnums`. |
|
||||
| **AppRightsBL, AppUser, AppGroup** | Zentrale Businesslogik- bzw. Entitätsklassen des internen Berechtigungsmodells. |
|
||||
| **DAOSession / Session** | Zugriffsschicht-Objekt (NHibernate-basiert), über das Businesslogikklassen auf Datenbank, Cache und Named Queries zugreifen. |
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Hypothesen — offene Verifikationsfragen
|
||||
|
||||
Sammlung aller mit `[HYPOTHESE]` markierten Aussagen aus StRS.md, SyRS.md und SwRS.md, mit der jeweils fehlenden Information zur Bestätigung.
|
||||
|
||||
---
|
||||
|
||||
### H-01: Namensbasierte Admin-Erkennung als fragile Altlast
|
||||
**Betroffene Anforderungen:** StRS-07, SyRS-11, SwRS-15
|
||||
**Beobachtung:** `IsAdmin()` prüft `g.Name == "Administratoren"` (String-Literal), nicht eine stabile Gruppen-ID.
|
||||
**Offene Frage:** Ist diese Kopplung an den Gruppennamen bewusstes Design (z. B. weil die Gruppe „Administratoren“ nicht umbenennbar/löschbar ist und dies an anderer Stelle technisch erzwungen wird) oder eine unentdeckte Schwachstelle?
|
||||
**Zur Bestätigung fehlt:** Prüfung, ob im Admin-UI ein Schutz gegen Umbenennen/Löschen dieser speziellen Gruppe existiert (z. B. eine Sonderbehandlung in `AppUserGroupBL.cs`, die nicht gelesen wurde).
|
||||
|
||||
---
|
||||
|
||||
### H-02: Auswertungsstelle von ShowHelpdeskRight nicht verifiziert
|
||||
**Betroffene Anforderungen:** StRS-13, SyRS-19, SwRS-26
|
||||
**Beobachtung:** Das Enum `ShowHelpdeskRight` (None/OnlyOwn/OnlyOwnAndNotify/All/OnlyOwnBranch) wurde in seiner Definition gefunden, nicht jedoch die konkrete Filterlogik, die es auswertet (z. B. in einer Ticketlisten-Suchmethode).
|
||||
**Offene Frage:** An welcher Stelle genau (welche Klasse/Methode) wird dieses Recht ausgewertet, und wirkt es serverseitig (SQL-WHERE-Klausel) oder nur clientseitig als UI-Filter?
|
||||
**Zur Bestätigung fehlt:** Gezielte Suche nach Verwendungsstellen von `ShowHelpdeskRight` in der Helpdesk-/Ticket-Suchlogik (z. B. `HelpdeskBL`, `TicketSearchBL` o. ä.), die im Rahmen dieser Iteration nicht durchgeführt wurde.
|
||||
|
||||
---
|
||||
|
||||
### H-03: Kein DB-Constraint für Belegstatus-Wertebereich gefunden
|
||||
**Betroffene Anforderungen:** StRS-02, SyRS-04
|
||||
**Beobachtung:** Die Bedeutung der Werte 1/2/3 für `State` ist nur über eine UI-Konvertierungsklasse (SEKUNDÄR) belegt. Es wurde kein CHECK-Constraint oder serverseitiges Enum-Mapping gefunden, das ungültige Werte (z. B. 0 oder 4) technisch verhindert.
|
||||
**Offene Frage:** Existiert eine DB-seitige Absicherung (Check-Constraint, Trigger) des Wertebereichs, die in der Codebasis nicht als Datei vorliegt (z. B. nur als DB-Migrationsskript außerhalb des durchsuchten Verzeichnisbaums)?
|
||||
**Zur Bestätigung fehlt:** Zugriff auf das tatsächliche Datenbankschema bzw. DB-Migrationsskripte, die im Repository nicht in durchsuchbarer Form (keine `.sql`-Dateien außerhalb von bin/obj gefunden) vorlagen.
|
||||
|
||||
---
|
||||
|
||||
### H-04: Diskrepanz zwischen Commit-Beschreibung „rights check“ und tatsächlicher Konfigurationsschalter-Logik
|
||||
**Betroffene Anforderungen:** StRS-05, SyRS-08, SwRS-10
|
||||
**Beobachtung:** Commit baa9e7bd9b beschreibt die Änderung als „rights check“, der Code liest jedoch `CentronCache.Instance.ReceiptSettings.CanChangeDateInInvoices/CanChangeDateInDeliveryLists` — einen globalen Konfigurationsschalter, keinen `HasUserRight(...)`-Aufruf. Der angezeigte Hinweistext spricht zusätzlich explizit von einem „Recht“.
|
||||
**Offene Frage:** Ist `CanChangeDateInInvoices`/`CanChangeDateInDeliveryLists` inhaltlich an ein Benutzerrecht gekoppelt (z. B. wird der Schalter selbst nur von berechtigten Benutzern gesetzt) oder handelt es sich um eine rein globale, für alle Benutzer gleiche Einstellung, die im Hinweistext irreführend als „Recht“ bezeichnet wird?
|
||||
**Zur Bestätigung fehlt:** Herkunft/Definition von `ReceiptSettings.CanChangeDateInInvoices` (Einstellungsseite, wer darf sie ändern) wurde nicht zurückverfolgt.
|
||||
|
||||
---
|
||||
|
||||
### H-05: Cache-Invalidierung bei Rechteänderung zur Laufzeit
|
||||
**Betroffene Anforderungen:** StRS-06, SyRS-09, SwRS-11
|
||||
**Beobachtung:** `HasUserRight` cacht die Rechteliste eines Benutzers pro Session unter dem Schlüssel `AllRightsFromAppUser{appUserI3D}`. Es wurde keine explizite Invalidierungslogik gefunden, die diesen Cache-Eintrag bei einer Rechteänderung (z. B. Entzug eines Rechts durch einen Administrator) zur Laufzeit zurücksetzt.
|
||||
**Offene Frage:** Wird der Cache beim nächsten Login automatisch neu aufgebaut (was eine akzeptable Verzögerung wäre), oder kann ein Benutzer mit bereits aktiver Session ein entzogenes Recht über die gesamte Sitzungsdauer hinweg weiterhin nutzen?
|
||||
**Zur Bestätigung fehlt:** Analyse der `Session.Advanced.Cache`-Implementierung (Lebensdauer, Scope: pro HTTP-Request, pro Login-Session oder pro Anwendungsprozess) — Cache-Infrastrukturklasse wurde nicht gelesen.
|
||||
|
||||
---
|
||||
|
||||
### H-06: Detailausprägung der WebAccount-Filterung in fünf weiteren Beleg-Klassen
|
||||
**Betroffene Anforderungen:** StRS-09, SyRS-13, SwRS-19
|
||||
**Beobachtung:** Nur `InvoiceBL.GetInvoiceByFilter` wurde im Detail gelesen und verifiziert. Für `OfferBL.cs`, `OrderBL.cs`, `ContractBL.cs`, `CreditVoucherBL.cs`, `DeliveryListBL.cs` liegt lediglich ein Grep-Treffer auf den Bezeichner `IsWebAccountLogin` vor.
|
||||
**Offene Frage:** Implementieren alle fünf Klassen exakt dasselbe Fail-Closed-Muster (leere Liste bei Kunden-Mismatch), oder gibt es Abweichungen (z. B. Exception statt leere Liste, oder eine Lücke in einer der Klassen)?
|
||||
**Zur Bestätigung fehlt:** Einzellektüre der jeweiligen Filter-/Suchmethoden in den fünf genannten Dateien.
|
||||
|
||||
---
|
||||
|
||||
### H-07: Reichweite des Admin-Bypasses über CentronChecklistWebserviceBL hinaus
|
||||
**Betroffene Anforderungen:** StRS-07, SyRS-11, SwRS-14
|
||||
**Beobachtung:** `IsAdmin()`-Aufrufe wurden zusätzlich in `DocumentationBL.cs` (5 Fundstellen) und `CampaignBL.cs` gefunden, aber nicht einzeln gelesen.
|
||||
**Offene Frage:** In wie vielen weiteren Modulen wird `IsAdmin()` als Zugriffs-Bypass verwendet, und ist dieses Verhalten dort ebenso dokumentiert/gewollt wie in `CentronChecklistWebserviceBL`?
|
||||
**Zur Bestätigung fehlt:** Vollständige Durchsicht aller ca. 9 gefundenen `IsAdmin()`-Aufrufstellen im Backend (nur 2 wurden inhaltlich geprüft).
|
||||
|
||||
---
|
||||
|
||||
## Hinweis zur Nutzung
|
||||
|
||||
Diese Hypothesen sind keine Mängel der Spezifikation, sondern bewusst offen gelassene Fragen gemäß der Randbedingung „Keine Halluzinationen“. Sie sollten in der manuellen Validierung (Schritt 7 der RRE-Methodenkette) durch Fachexperten und/oder in einer Folge-Iteration mit erweitertem Leseumfang geklärt werden (siehe auch `Analysebericht.md`, Abschnitt „Empfehlungen für Folge-Iteration“).
|
||||
+345
@@ -0,0 +1,345 @@
|
||||
# Stakeholder Requirements Specification (StRS) — c-entron ERP
|
||||
|
||||
Ebene 1 von 3 (StRS → SyRS → SwRS) nach ISO/IEC/IEEE 29148:2018. Fachliche Sicht: Geschäftsziele, Akteure, Geschäftsprozesse, wie sie sich aus der Implementierung der Codebasis `CentronERP` erschließen lassen.
|
||||
|
||||
Zur Belegklassifikation, Statuswerten und zum Umfang der Analyse siehe `Analysebericht.md`. Alle referenzierten Domänenbegriffe sind in `Glossar.md` definiert.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: StRS-01
|
||||
Titel: Versionierte Kundenbelege statt Überschreiben
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb, Fakturierung, System
|
||||
Vorbedingung: Ein Kundenbeleg (Angebot, Auftrag, Lieferschein, Rechnung, Gutschrift, Vertrag) existiert bereits in einem nicht-neuen Zustand.
|
||||
Fakt: Alle Beleg-Businesslogikklassen erben von `AssetBL<T,V>`, welche eine Methode `CreateNewVersion(...)` bereitstellt, die `Version` inkrementiert, `MaxVersion` nachzieht und `IsNewVersion=true` setzt, statt den bestehenden Datensatz direkt zu ändern.
|
||||
Aussage: Das System soll inhaltliche Änderungen an einem bereits abgeschlossenen oder fixierten Kundenbeleg als neue Version desselben Belegs führen, damit der ursprüngliche Beleginhalt nachvollziehbar erhalten bleibt.
|
||||
Ergebnis: Der Beleg erhält eine neue, höhere Versionsnummer; die vorherige Version bleibt im Datenbestand auffindbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Methoden `CreateNewVersion` (Z. 955–1016) und `DoCreateNewVersion` (Z. 1026–1032: `asset.Version += 1; asset.MaxVersion = asset.Version; asset.IsNewVersion = true;`) - Begründung: Zeigt den durchgesetzten Versionierungsmechanismus als Basisverhalten aller abgeleiteten Beleg-BL-Klassen (Offer/Order/Invoice/DeliveryList/CreditVoucher/Contract).
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/CustomerAssets/AssetBase.cs, Felder `State`, `OriginalI3D` (Z. 24–25) - Begründung: Belegt, dass Version/OriginalI3D feste Datenmodellfelder aller Kundenbelege sind.
|
||||
- [KONTEXT] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Z. 632–674 (`GetNewAsset`: `objAsset.Version = 1; objAsset.MaxVersion = 1; objAsset.OldVersion = 1;`) - Begründung: Zeigt Initialwerte bei Neuanlage, als Kontrast zur Versionsfortschreibung.
|
||||
Prüfidee: Einen fixierten Auftrag ändern und prüfen, dass `Version` erhöht und der alte Datensatz weiterhin per `OriginalI3D`/Vorgängerversion referenzierbar ist.
|
||||
Tracelinks: SyRS-01, SyRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-02
|
||||
Titel: Stornierte Rechnungen bleiben als Beleg erhalten
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierung, Buchhaltung
|
||||
Vorbedingung: Eine Rechnung wurde erstellt und soll storniert werden.
|
||||
Fakt: `InvoiceBL.CancelInvoice(Invoice asset, AppUser currUser)` erzeugt über `CreateNewVersion` eine neue Version der Rechnung, setzt `newAsset.State = 3` und setzt die Menge jeder Position auf 0, statt den Beleg zu löschen.
|
||||
Aussage: Das System soll eine stornierte Rechnung nicht löschen, sondern als neue, mengenreduzierte Version mit dem Status „abgebrochen“ fortführen, damit der Rechnungsvorgang für Buchhaltungs- und Prüfzwecke nachvollziehbar bleibt.
|
||||
Ergebnis: Es existiert weiterhin ein Belegdatensatz mit Status „abgebrochen“ (State=3) und Positionsmengen von 0; die Original-Rechnungsdaten bleiben in der Vorgängerversion erhalten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Methode `CancelInvoice` (Z. 392–411) - Begründung: Durchgesetzte Implementierung des Stornoprozesses; kein Lösch-Aufruf vorhanden.
|
||||
- [SEKUNDÄR] src/shared/Centron.Controls/Converters/StateToStringConverter.cs (Z. 13–18: 1=„offen“, 2=„abgeschlossen“, 3=„abgebrochen“) - Begründung: UI-seitige Beschriftung bestätigt die fachliche Bedeutung von State=3 als Storno/Abbruch.
|
||||
Prüfidee: Rechnung stornieren und prüfen: (a) neue Version wird angelegt, (b) State der neuen Version = 3, (c) Positionsmengen = 0, (d) Vorgängerversion bleibt abrufbar.
|
||||
Tracelinks: SyRS-03, SyRS-04
|
||||
Konsolidierung: Kandidat: Analoge Stornoabläufe in OrderBL/OfferBL/DeliveryListBL/CreditVoucherBL wurden nicht im Detail geprüft (siehe Analysebericht.md) und sollten auf einheitliche Umsetzung verglichen werden.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-03
|
||||
Titel: Automatisierte Sammelfakturierung offener Lieferscheine/Aufträge
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierung
|
||||
Vorbedingung: Es existieren abgeschlossene, noch nicht fakturierte Lieferscheine oder Aufträge für einen Kunden bis zu einem Stichtag.
|
||||
Fakt: `AutomaticFacturaBL` stellt Methoden `SearchBillingDeliveryLists(DateTime endDate, int customerI3D)`, `SearchBillingOrders(DateTime endDate, int customerI3D, bool searchForInvoice)` und `SearchCustomers(DateTime BilledTo)` bereit, die abrechnungsfähige Belege je Kunde und Stichtag ermitteln.
|
||||
Aussage: Das System soll offene, abrechnungsfähige Lieferscheine und Aufträge je Kunde bis zu einem definierten Stichtag automatisiert ermitteln und zu einer Sammelabrechnung zusammenführen können.
|
||||
Ergebnis: Eine Liste abrechnungsfähiger Belege pro Kunde/Stichtag steht als Grundlage für eine automatisch erzeugte Rechnung zur Verfügung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs, Methoden `SearchBillingDeliveryLists` (Z. 102), `SearchBillingOrders` (Z. 114), `SearchCustomers` (Z. 451) - Begründung: Zentrale, durchgesetzte Suchlogik für die Sammelfakturierung.
|
||||
- [KONTEXT] ebd., Klassenkommentar Z. 51–53 „Contains logic for automatic factura.“ - Begründung: Bestätigt die fachliche Zweckbestimmung der Klasse.
|
||||
Prüfidee: Für einen Kunden mit zwei offenen Lieferscheinen vor Stichtag und einem nach Stichtag prüfen, dass nur die beiden ersten in der Ergebnisliste erscheinen.
|
||||
Tracelinks: SyRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-04
|
||||
Titel: Vertragsbasierte wiederkehrende Abrechnung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierung, Vertragsmanagement
|
||||
Vorbedingung: Ein Kundenvertrag mit Beginn-Datum, Laufzeitart und Laufzeitdauer ist angelegt.
|
||||
Fakt: `ContractBL` verwendet ein Enum `BillingIntervalKinds` (u. a. `Monthly`, `Quarterly`, `Yearly`, Z. 1021–1027) sowie Vertragsfelder `Beginn`, `LaufzeitArt`, `LaufzeitDauer` (Z. 1086), um über `GetNewDate(...)` das nächste Abrechnungs-/Laufzeitende zu berechnen.
|
||||
Aussage: Das System soll auf Basis von Vertragsbeginn, Laufzeitart und -dauer automatisch wiederkehrende Abrechnungszeiträume (monatlich, quartalsweise, jährlich) ermitteln.
|
||||
Ergebnis: Für einen Vertrag wird ein korrektes nächstes Laufzeitende/Abrechnungsdatum berechnet, das die Basis für automatisiert erzeugte Rechnungspositionen bildet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs, `switch`-Fälle Z. 1021–1027 (`BillingIntervalKinds.Monthly/Yearly/Quarterly`) sowie Z. 1086–1093 (`GetNewDate(contract.Beginn.Value, contract.LaufzeitArt.Value, contract.LaufzeitDauer.Value)`) - Begründung: Durchgesetzte Berechnungslogik für Vertragsintervalle.
|
||||
- [PRIMÄR] ebd., `GetContractBillingPeriodForInvoiceItem` / NamedQuery `GetContractBillingPeriodForCreditVoucherItem` (Z. 324–335) - Begründung: Belegt die Verknüpfung von Vertragslaufzeit zu konkreten Rechnungs-/Gutschriftpositionen.
|
||||
Prüfidee: Vertrag mit Beginn 01.01., LaufzeitArt=Monatlich, LaufzeitDauer=1 anlegen und prüfen, dass das berechnete nächste Datum der 01.02. ist.
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-05
|
||||
Titel: Zeiterfassungsbasierte Abrechnung (TimerBilling)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Servicetechniker, Fakturierung
|
||||
Vorbedingung: Zeiterfassungen (Ticket-Timer) wurden zu Vorgängen erfasst und sollen abgerechnet werden.
|
||||
Fakt: `TimerBillingSettingsPageViewModel` erlaubt die Wahl des Zielbelegtyps (`ReceiptKind`: `InvoiceClass`/`DeliveryListClass`) und eines Abrechnungsdatums (`BillingDate`), dessen Änderbarkeit über `UpdateBillingDateIsEnabled()` konfigurationsabhängig gesteuert wird.
|
||||
Aussage: Das System soll erfasste Zeiten wahlweise zu Rechnungen oder Lieferscheinen verdichten können, wobei die Änderbarkeit des Abrechnungsdatums über eine zentrale Einstellung steuerbar ist.
|
||||
Ergebnis: Ein Beleg des gewählten Typs mit den verdichteten Zeitpositionen wird erzeugt; das Abrechnungsdatum ist nur änderbar, wenn die zugehörige Einstellung dies zulässt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, Property `ReceiptKind` (Z. ~195–200) und Methode `UpdateBillingDateIsEnabled()` (Z. 566–588, aus Commit baa9e7bd9b) - Begründung: Durchgesetzte UI-/Steuerungslogik für Zielbelegtyp und Datumsänderbarkeit.
|
||||
- [KONTEXT] Commit baa9e7bd9b „feat: added rights check for editing invoice or delivery list date in the settings of timer billing...“ - Begründung: Bestätigt fachliche Motivation (Einschränkung der Datumsänderung) und Zeitpunkt der Einführung.
|
||||
Prüfidee: TimerBilling-Einstellungsseite öffnen, `ReceiptKind` zwischen Rechnung/Lieferschein wechseln und prüfen, dass der Hinweistext bei fehlender Berechtigung/Einstellung erscheint.
|
||||
Tracelinks: SyRS-07, SyRS-08
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-06
|
||||
Titel: Gruppenbasiertes Berechtigungsmodell (interne Benutzer)
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator, alle internen Benutzer
|
||||
Vorbedingung: Ein Benutzer ist einer oder mehreren Benutzergruppen zugeordnet.
|
||||
Fakt: Rechte werden ausschließlich Gruppen zugeordnet (Tabellen `Sichtrus`/`Sichmemb`); ein Benutzer erhält seine Rechte durch Mitgliedschaft in Gruppen (`AppRightsBL.GetRightsFromCurrentUser` aggregiert `group.Rights` über `user.Groups`). Es existiert keine Zuweisung einzelner Rechte direkt an einen Benutzer.
|
||||
Aussage: Das System soll Berechtigungen ausschließlich über Gruppenzugehörigkeit vergeben; ein Benutzer erbt alle Rechte der ihm zugeordneten Gruppen.
|
||||
Ergebnis: Die Summe der Rechte eines Benutzers entspricht der Vereinigungsmenge der Rechte seiner Gruppen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Methode `GetRightsFromCurrentUser` (Z. 63–87: `foreach (AppGroup group in user.Groups) rights.AddRange(group.Rights);`) - Begründung: Durchgesetzte Aggregationslogik, die Rechte ausschließlich über Gruppen bezieht.
|
||||
- [PRIMÄR] ebd., Methode `GetAllAppRightsFromUser` (Z. 651–664) mit SQL `SELECT st.Recht FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D` - Begründung: DB-seitig durchgesetztes Gruppen-Recht-Modell (Sichtrus=Recht-je-Gruppe, Sichmemb=Benutzer-in-Gruppe).
|
||||
Prüfidee: Einem Benutzer ein Recht ausschließlich über eine neue Gruppenzuordnung erteilen und prüfen, dass `HasUserRight` anschließend `true` liefert.
|
||||
Tracelinks: SyRS-09, SyRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-07
|
||||
Titel: Administratorgruppe mit implizitem Vollzugriff
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator
|
||||
Vorbedingung: Ein Benutzer ist Mitglied der Gruppe „Administratoren“.
|
||||
Fakt: `UserRightsExt.IsAdmin()` prüft, ob der Benutzer einer Gruppe mit dem Namen `UserRightsConst.ADMIN_ACCOUNT` ("Administratoren") angehört. An mehreren Stellen (u. a. `CentronChecklistWebserviceBL.cs` Z. 87, 160) wird `IsAdmin()` als ODER-Bedingung verwendet, die eine sonst erforderliche Einzelrechtprüfung ersetzt.
|
||||
Aussage: Das System soll Mitgliedern der Administratorgruppe an bestimmten, individuell im Code verankerten Stellen impliziten Zugriff gewähren, unabhängig vom Ergebnis der granularen Rechteprüfung.
|
||||
Ergebnis: Ein Administrator kann die betroffene Funktion nutzen, auch wenn ihm das spezifische Einzelrecht nicht explizit zugewiesen wurde.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/WebServices/CheckListArea/CentronChecklistWebserviceBL.cs, Z. 87 (`if (loggedInUser.User.IsAdmin()) return true;`) und Z. 160 (`if (loggedInUser.User.IsAdmin() || loggedInUser.User.HasUserRight(UserRightsConst.Administration.SETTINGS)) return (true, string.Empty);`) - Begründung: Durchgesetzter Code-Beleg für den Admin-Bypass in einem konkreten Modul.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs, Methode `IsAdmin()` (Z. 56–66) - Begründung: Zentrale Definition der Admin-Prüfung über Gruppennamen.
|
||||
- [KONTEXT] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs, Z. 20 (`ADMIN_ACCOUNT = "Administratoren"`) - Begründung: Zeigt, dass die Admin-Erkennung an einen festen, umbenennbaren Gruppennamen (String) gekoppelt ist, nicht an eine stabile ID.
|
||||
Prüfidee: Benutzer ohne Recht „SETTINGS“, aber in Gruppe „Administratoren“, ruft geschützte Funktion auf und erhält Zugriff.
|
||||
Tracelinks: SyRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (Namensbasierte statt ID-basierte Admin-Erkennung ist eine fragile Altlast; siehe Hypothesen.md H-01)
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-08
|
||||
Titel: Getrenntes Rechtemodell für Kundenportal-Zugänge
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Kundenportal-Benutzer (WebAccount), Administrator
|
||||
Vorbedingung: Ein externer Kunde besitzt einen WebAccount-Zugang zum Kundenportal.
|
||||
Fakt: Für WebAccounts existiert ein eigenständiges Rechtesystem (`WebAccountsRights`-Tabelle, geprüft über `AppRightsBL.CheckWebRightsFromUser`/`HasWebAccountRight`), das getrennt vom internen Sichtrus/Sichmemb-Modell für Mitarbeiter geführt wird.
|
||||
Aussage: Das System soll für Kundenportal-Zugänge ein eigenständiges, von internen Mitarbeiterrechten unabhängiges Berechtigungsmodell führen.
|
||||
Ergebnis: Rechte eines WebAccounts werden ausschließlich über `WebAccountsRights` geprüft; interne Mitarbeiterrechte (Sichtrus/Sichmemb) sind für WebAccounts nicht wirksam.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Methode `CheckWebRightsFromUser` (Z. 113–120) mit SQL gegen `WebAccountsRights` - Begründung: Durchgesetzte, von Sichtrus/Sichmemb getrennte Datenquelle für Web-Rechte.
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs, `HasWebRight(this WebAccount, ...)` Extension-Methoden (Z. 34–47) - Begründung: Zeigt eigenständige API-Oberfläche für Web-Rechteprüfung parallel zu `HasUserRight`.
|
||||
Prüfidee: Einem WebAccount ein Web-Recht zuweisen und prüfen, dass dies keine Auswirkung auf interne `Sichtrus`-Rechte desselben zugrunde liegenden Kunden hat (und umgekehrt).
|
||||
Tracelinks: SyRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-09
|
||||
Titel: Datenisolation im Kundenportal auf eigene Belege
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Kundenportal-Benutzer (WebAccount)
|
||||
Vorbedingung: Ein WebAccount-Benutzer ist angemeldet und fragt Belege (Rechnungen, Angebote, Aufträge etc.) ab.
|
||||
Fakt: In den Such-/Filtermethoden mehrerer Beleg-BL-Klassen (u. a. `InvoiceBL.GetInvoiceByFilter`) wird bei `currentUser.IsWebAccountLogin == true` geprüft, ob `filter.CustomerI3D == currentUser.WebAccount.CustomerI3D`; bei Abweichung wird eine leere Ergebnisliste zurückgegeben.
|
||||
Aussage: Das System soll Kundenportal-Benutzern ausschließlich den Zugriff auf Belege des eigenen, dem WebAccount zugeordneten Kundenkontos gestatten.
|
||||
Ergebnis: Abfragen mit abweichender Kunden-I3D liefern für WebAccount-Logins keine Datensätze, unabhängig vom übergebenen Filter.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 437–438 (`if (currentUser != null && currentUser.IsWebAccountLogin && filter.CustomerI3D != currentUser.WebAccount.CustomerI3D) return new PagingList<InvoiceCompact>();`) - Begründung: Durchgesetzte serverseitige Datenisolation, nicht nur UI-Filterung.
|
||||
- [SEKUNDÄR] Vorkommen des Musters `IsWebAccountLogin` zusätzlich in OfferBL.cs, OrderBL.cs, ContractBL.cs, CreditVoucherBL.cs, DeliveryListBL.cs (Fundstellen nicht im Detail geprüft) - Begründung: Deutet auf ein wiederkehrendes, modulübergreifendes Muster hin; Tiefe der Prüfung siehe Analysebericht.md.
|
||||
Prüfidee: Als WebAccount mit `CustomerI3D=100` eine Abfrage mit `filter.CustomerI3D=200` senden und prüfen, dass die Ergebnisliste leer ist.
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: Kandidat: Einheitliches Cross-Cutting-Konzern-Pattern über alle sechs Beleg-BL-Klassen hinweg; im Zielsystem als zentraler Autorisierungsfilter statt Einzelprüfung je Methode konsolidierbar.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-10
|
||||
Titel: Zwei-Faktor-Authentifizierung für sensible Vorgänge
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Benutzer, System
|
||||
Vorbedingung: Einem Benutzer ist in der Personalverwaltung ein Zwei-Faktor-Schlüssel hinterlegt.
|
||||
Fakt: `TwoFactorAuthenticationBL.ValidateAuthenticationPin` validiert eine vom Benutzer eingegebene PIN gegen einen gespeicherten TOTP-Schlüssel mittels `Centron.Core.GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin`.
|
||||
Aussage: Das System soll eine zeitbasierte Zwei-Faktor-Authentifizierung (TOTP) unterstützen, bei der die PIN serverseitig gegen einen je Benutzer hinterlegten Schlüssel geprüft wird.
|
||||
Ergebnis: Bei korrekter PIN wird der Vorgang als erfolgreich bestätigt; bei fehlendem Schlüssel oder falscher PIN wird ein spezifischer Fehler zurückgegeben.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Methode `ValidateAuthenticationPin` (Z. 43–54) - Begründung: Durchgesetzte serverseitige TOTP-Prüfung inkl. Fehlermeldungstexte.
|
||||
- [SEKUNDÄR] ebd., Fehlermeldung „Ihrem Benutzer ist kein Zwei-Faktor Schlüssel in der Personalverwaltung hinterlegt!“ (Z. 48) - Begründung: UI-nahe Fehlermeldung bestätigt fachlichen Ablageort (Personalverwaltung) des Schlüssels.
|
||||
Prüfidee: Benutzer ohne hinterlegten Schlüssel führt Validierung durch und erhält die definierte Fehlermeldung statt eines Erfolgs.
|
||||
Tracelinks: SyRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-11
|
||||
Titel: Digitale PDF-Signatur von Dokumenten inkl. Zeitstempeldienst
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Administrator, System, Kunde (Empfänger)
|
||||
Vorbedingung: Ein Zertifikat und ein Zeitstempeldienst (TSA) sind konfiguriert.
|
||||
Fakt: `PdfSigningBL` verwaltet Einstellungen für digitale PDF-Signatur inkl. Zertifikat, TSA-Server-URL/-Zugangsdaten sowie Signaturgrund und -ort (`GetPdfSigningSettings`/`SavePdfSigningSettings`) unter Nutzung von `DevExpress.Office.DigitalSignatures`/`DevExpress.Office.Tsp`.
|
||||
Aussage: Das System soll PDF-Dokumente digital signieren und dabei optional einen externen Zeitstempeldienst (TSA) einbinden können, um die Signatur mit einem vertrauenswürdigen Zeitpunkt zu versehen.
|
||||
Ergebnis: Ein signiertes PDF-Dokument mit gültiger digitaler Signatur (und ggf. Zeitstempel) steht zur Weitergabe an Kunden zur Verfügung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Methoden `GetPdfSigningSettings` (Z. 29–55) und `SavePdfSigningSettings` (Z. 57 ff.) - Begründung: Durchgesetzte Konfigurationslogik für Zertifikat und TSA-Anbindung.
|
||||
- [KONTEXT] Commits 89ccfd650d „Ticket 168496 & 169060 - C-Sign (WebOffer & Acceptance)“ und cf27c00580 „Fix c-sign document preview and signing document“ - Begründung: Bestätigen den fachlichen Kontext einer Signatur-/Unterschriftsfunktion („C-Sign“) im aktuellen Entwicklungszeitraum.
|
||||
Prüfidee: Mit gültigem Zertifikat und konfiguriertem TSA-Server ein PDF signieren und die Signatur inkl. Zeitstempel technisch verifizieren.
|
||||
Tracelinks: SyRS-15, SyRS-16, SyRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-12
|
||||
Titel: Konfigurierbare Ticket-/Vorgangsstatus als Stammdaten
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Administrator, Support-Mitarbeiter
|
||||
Vorbedingung: Das Helpdesk-/Ticketmodul ist im Einsatz.
|
||||
Fakt: `HelpdeskState`/`HelpdeskStateBase` ist eine Entität mit editierbaren Feldern (`Icon`, `IsDeactivated`, `IsInternalCompanyBillingActive`, `ServiceBoardWebColor`, `ServiceBoardWebIcon`); Ticketstatus ist somit eine Stammdatentabelle und kein fest im Code verankertes Enum.
|
||||
Aussage: Das System soll Ticket-/Vorgangsstatus als vom Administrator pflegbare Stammdaten (inkl. Icon, Farbe, Aktivierung, Verrechnungsrelevanz) führen statt als starre Programmkonstante.
|
||||
Ergebnis: Neue Status können ohne Codeänderung angelegt, deaktiviert oder in Darstellung/Verrechnung angepasst werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskState.cs (Z. 1–16) und HelpdeskStateBase.cs - Begründung: Entitätsdefinition belegt Stammdatencharakter (persistente, editierbare Objekte statt Enum-Literale).
|
||||
Prüfidee: Einen neuen Ticketstatus mit eigenem Icon/Farbe anlegen und prüfen, dass er in der Statusauswahl eines Tickets erscheint, ohne dass Code geändert wurde.
|
||||
Tracelinks: SyRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-13
|
||||
Titel: Sichtbarkeitsscoping von Tickets nach Zuständigkeit
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Support-Mitarbeiter, Administrator
|
||||
Vorbedingung: Mehrere Support-Mitarbeiter und Niederlassungen existieren im Mandanten.
|
||||
Fakt: Das Enum `ShowHelpdeskRight` (`None`, `OnlyOwn`, `OnlyOwnAndNotify`, `All`, `OnlyOwnBranch`) definiert fünf abgestufte Sichtbarkeitsstufen für Tickets.
|
||||
Aussage: Das System soll die Sichtbarkeit von Tickets für einen Benutzer auf „keine“, „nur eigene“, „nur eigene inkl. Benachrichtigung“, „alle“ oder „nur eigene Niederlassung“ einschränken können.
|
||||
Ergebnis: Ein Benutzer sieht in Ticketlisten nur die gemäß seiner zugewiesenen Sichtbarkeitsstufe zulässigen Tickets.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Helpdesks/ShowHelpdeskRight.cs (Z. 1–10) - Begründung: Enum-Definition belegt das Vorhandensein der fünf Sichtbarkeitsstufen als Rechtekonzept.
|
||||
Prüfidee: Benutzer mit `OnlyOwnBranch` meldet sich an und prüft, dass nur Tickets der eigenen Niederlassung in der Liste erscheinen.
|
||||
Tracelinks: SyRS-19
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE] die konkrete Auswertungsstelle des Enums (welche Abfrage die Filterung tatsächlich anwendet) wurde nicht verifiziert — siehe Hypothesen.md H-02.
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-14
|
||||
Titel: Artikel-Bestandsführung: Seriennummer vs. Menge
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Lager, Einkauf
|
||||
Vorbedingung: Ein Artikel ist im Artikelstamm angelegt.
|
||||
Fakt: In `ArticleBL.cs` (Z. 2783) entscheidet das Flag `A.BarcodeScanen`, ob der verfügbare Bestand über `dbo.cfn_BarcodeCount(A.I3D,0)` (Zählung einzelner Barcodes/Seriennummern) oder über `SUM(NA.Bestand)` aus der Tabelle `NebenlagerArtikel` (Mengenbestand je Nebenlager) ermittelt wird.
|
||||
Aussage: Das System soll je Artikel wahlweise eine seriennummerngenaue Bestandsführung (Barcode-Zählung) oder eine mengenbasierte Bestandsführung (Summenbildung über Lagerorte) unterstützen.
|
||||
Ergebnis: Die Bestandsanzeige eines Artikels entspricht je nach Konfiguration entweder der Anzahl erfasster Barcodes oder der Summe der Lagerbestandsmengen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Z. 2783 (`CASE WHEN A.BarcodeScanen = 1 THEN dbo.cfn_BarcodeCount(A.I3D,0) ELSE ISNULL((SELECT SUM(ISNULL(NA.Bestand,0)) FROM NebenlagerArtikel NA WHERE NA.ArtikelI3D = A.I3D),0) END`) - Begründung: Durchgesetzte, DB-seitige Fallunterscheidung als Teil einer SQL-Abfrage.
|
||||
Prüfidee: Für einen Artikel mit `BarcodeScanen=1` zwei Barcodes erfassen und prüfen, dass der Bestand 2 beträgt, unabhängig vom `Bestand`-Feld in `NebenlagerArtikel`.
|
||||
Tracelinks: SyRS-20
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-15
|
||||
Titel: Automatische Übernahme kundenindividueller Finanzkonditionen
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb, System
|
||||
Vorbedingung: Ein Kunde mit hinterlegten Finanzinformationen existiert; ein neuer Beleg wird für diesen Kunden angelegt.
|
||||
Fakt: `CustomerAssetBL.GetNewAsset` übernimmt beim Anlegen eines neuen Belegs u. a. `Discount`, `ExclusiveOfVAT` (aus `financeInfo.VATNotActive`), `PaymentCondition` sowie `Currency`/`CurrencyFactor` aus `CustomerFinanceInfo` des Kunden in den Belegkopf.
|
||||
Aussage: Das System soll beim Anlegen eines neuen Kundenbelegs automatisch die für den Kunden hinterlegten Finanzkonditionen (Zahlungsbedingung, Rabatt, USt-Befreiung, Währung) in den Beleg übernehmen.
|
||||
Ergebnis: Ein neu angelegter Beleg trägt bereits die kundenspezifischen Finanzwerte, ohne dass diese manuell erfasst werden müssen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/CustomerAssetBL.cs, Z. 136–145 (`CustomerFinanceInfo financeInfo = ...; objAsset.IgnoreDiscount = financeInfo.DontShowRabateText; objAsset.ExclusiveOfVAT = financeInfo.VATNotActive; objAsset.Discount = ...; objAsset.PaymentCondition = ...`) - Begründung: Durchgesetzte Übernahmelogik im gemeinsamen Basiscode aller Kundenbelegarten.
|
||||
Prüfidee: Kunde mit Rabatt=10% und Zahlungsziel „30 Tage netto“ anlegen; neuen Auftrag für diesen Kunden erstellen und prüfen, dass beide Werte im Beleg vorbelegt sind.
|
||||
Tracelinks: SyRS-21
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-16
|
||||
Titel: Automatisches Mahndatum für offene Rechnungen
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierung, Buchhaltung
|
||||
Vorbedingung: Eine Rechnung wurde erstellt; eine Frist für Zahlungserinnerungen ist als Systemeinstellung konfiguriert.
|
||||
Fakt: `InvoiceBL.SetReminderDate` liest die Einstellung `AppSettingsConst.InvoiceReminderDays` und setzt, falls > 0, `asset.ReminderDate = DateTime.Today.AddDays(setting)`.
|
||||
Aussage: Das System soll für Rechnungen automatisch ein Erinnerungsdatum auf Basis einer zentral konfigurierbaren Fristvorgabe (in Tagen) setzen können.
|
||||
Ergebnis: Die Rechnung erhält ein `ReminderDate`, das dem aktuellen Datum zzgl. der konfigurierten Tagesanzahl entspricht.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Methode `SetReminderDate` (Z. 417–427) - Begründung: Durchgesetzte, konfigurationsgesteuerte Berechnung des Erinnerungsdatums.
|
||||
Prüfidee: `InvoiceReminderDays=14` konfigurieren, Rechnung anlegen und prüfen, dass `ReminderDate` = heute + 14 Tage beträgt; bei Einstellung 0/nicht gesetzt bleibt `ReminderDate` unverändert.
|
||||
Tracelinks: SyRS-22
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-17
|
||||
Titel: Rollenbasierter Zugriffsschutz für Web-API-Endpunkte
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: API-Client, System
|
||||
Vorbedingung: Ein API-Endpunkt ist mit einem oder mehreren erforderlichen Rechten annotiert.
|
||||
Fakt: Die Controller-Schicht stellt drei Autorisierungs-Attribute bereit (`AuthorizeUserRightAttribute`, `AuthorizeAnyUserRightAttribute`, `AuthorizeAllUserRightsAttribute`), die bei fehlender Anmeldung HTTP 401 und bei fehlendem/fehlenden Recht(en) HTTP 403 liefern.
|
||||
Aussage: Das System soll Web-API-Endpunkte deklarativ über Rechte-Attribute absichern und dabei einheitlich zwischen „nicht angemeldet“ (401) und „nicht berechtigt“ (403) unterscheiden.
|
||||
Ergebnis: Anfragen ohne gültige Anmeldung erhalten 401; Anfragen mit Anmeldung aber ohne ausreichendes Recht erhalten 403; nur berechtigte Anfragen erreichen die Controller-Aktion.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs (Z. 38–56) - Begründung: Kernimplementierung der Einzelrechtprüfung mit expliziter 401/403-Unterscheidung.
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeAnyUserRightAttribute.cs (Z. 38–58) und AuthorizeAllUserRightsAttribute.cs (Z. 38–58) - Begründung: Ergänzende ODER-/UND-Verknüpfung mehrerer Rechte, gleiches Antwortschema.
|
||||
Prüfidee: Endpunkt mit `[AuthorizeUserRight(X)]` ohne Session aufrufen → 401; mit Session aber ohne Recht X aufrufen → 403; mit Recht X aufrufen → 200.
|
||||
Tracelinks: SyRS-23, SyRS-24
|
||||
Konsolidierung: Kandidat: Die drei Attribute teilen nahezu identische Filterlogik (Unterschied nur in Any/All/Single-Verknüpfung) und könnten im Zielsystem auf einen parametrisierten Autorisierungsfilter konsolidiert werden.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-18
|
||||
Titel: Verschlüsselte Speicherung sensibler Zugangsdaten
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator, System
|
||||
Vorbedingung: Zugangsdaten zu externen Diensten (z. B. TSA-Server, Signaturzertifikat) werden im System hinterlegt.
|
||||
Fakt: `PdfSigningBL` verschlüsselt TSA-Server-Passwort und Zertifikatspasswort vor der Persistierung mit `AESCryptoLogic.EncryptText(...)` und entschlüsselt sie beim Lesen wieder mit `DecryptText(...)`.
|
||||
Aussage: Das System soll sensible, extern benötigte Zugangsdaten (Passwörter, Zertifikats-Credentials) ausschließlich verschlüsselt in der Konfiguration ablegen.
|
||||
Ergebnis: In der Konfigurationsdatenbank liegt kein Klartext-Passwort für TSA-Zugang oder Zertifikat vor.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 47–49 (`_cryptoLogic.DecryptText(...)`) und Z. 86–91 (`_cryptoLogic.EncryptText(...)` für Zertifikat und Zertifikatspasswort) sowie Z. 98–100 (Verschlüsselung TSA-Passwort) - Begründung: Durchgesetzte Ver-/Entschlüsselung an den konkreten Speicher-/Lesepunkten.
|
||||
Prüfidee: TSA-Passwort speichern und den Rohwert in der Einstellungstabelle prüfen — er darf nicht dem eingegebenen Klartext entsprechen.
|
||||
Tracelinks: SyRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+564
@@ -0,0 +1,564 @@
|
||||
# Software Requirements Specification (SwRS) — c-entron ERP
|
||||
|
||||
Ebene 3 von 3 (StRS → SyRS → SwRS) nach ISO/IEC/IEEE 29148:2018. Komponentenebene: konkrete Klassen, Methoden, Felder, SQL-Fragmente und Konfigurationsschlüssel.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: SwRS-01
|
||||
Titel: AssetBL.CreateNewVersion inkrementiert Versionsfelder
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: AssetBL<T,V>
|
||||
Vorbedingung: `CreateNewVersion(AppUser, T asset, out string message, bool refreshAsset)` wird aufgerufen.
|
||||
Fakt: `DoCreateNewVersion` setzt `asset.Version += 1; asset.MaxVersion = asset.Version; asset.IsNewVersion = true;` (Z. 1026–1032), eingebettet zwischen `DoBeforeCreateNewVersion` (Z. 1019) und `DoAfterCreateNewVersion` (Z. 1034).
|
||||
Aussage: Die Komponente `AssetBL<T,V>` soll bei jedem Aufruf von `CreateNewVersion` genau eine Versionserhöhung um 1 durchführen und `MaxVersion` synchron nachziehen.
|
||||
Ergebnis: `asset.Version` ist nach dem Aufruf um genau 1 höher als zuvor; `asset.MaxVersion == asset.Version`.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Z. 955–1032 - Begründung: Direkter Codebeleg der Feldänderung.
|
||||
Prüfidee: Unit-Test: `asset.Version` vor/nach Aufruf vergleichen, Differenz muss exakt 1 sein.
|
||||
Tracelinks: SyRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-02
|
||||
Titel: AssetBase führt gemeinsame Versions- und Statusfelder
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: AssetBase (Basisklasse aller Kundenbelege)
|
||||
Vorbedingung: Eine konkrete Belegentität (Offer/Order/Invoice/DeliveryList/CreditVoucher/Contract) wird instanziiert.
|
||||
Fakt: `AssetBase` definiert `public virtual int State { get; set; }` (Z. 24) und `public virtual int OriginalI3D { get; set; }` (Z. 25) als gemeinsame Basisfelder; `Version`/`MaxVersion`/`OldVersion`/`IsNewVersion` werden in `GetNewAsset` (Z. 643–647) initialisiert, ihre Feld-Deklaration selbst liegt außerhalb der eingesehenen Ausschnitte.
|
||||
Aussage: Die Entität `AssetBase` soll `State` und `OriginalI3D` als für alle Belegarten einheitliche, ererbte Felder bereitstellen.
|
||||
Ergebnis: Jede von `AssetBase` abgeleitete Belegentität besitzt exakt diese Felder mit identischer Semantik.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/CustomerAssets/AssetBase.cs, Z. 21–27 - Begründung: Direkte Felddeklaration in der gemeinsamen Basisklasse.
|
||||
Prüfidee: Reflektion über eine beliebige abgeleitete Klasse (z. B. `Invoice`) prüfen, dass `State`/`OriginalI3D` vorhanden und vom Typ `int` sind.
|
||||
Tracelinks: SyRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-03
|
||||
Titel: Barcode-Historieneintrag übernimmt Versionsnummer der Belegposition
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: AssetBL<T,V>
|
||||
Vorbedingung: Eine Belegposition mit gebundenem Barcode wird im Rahmen einer neuen Version verarbeitet.
|
||||
Fakt: `objHistory.Version = pos.Owner.Version;` (AssetBL.cs, Z. 478) innerhalb der Barcode-Historisierungslogik.
|
||||
Aussage: Die Komponente soll beim Anlegen eines Barcode-Historieneintrags stets die aktuelle Versionsnummer der zugehörigen Belegposition übernehmen.
|
||||
Ergebnis: Jeder Historieneintrag ist eindeutig einer Belegversion zuordenbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Z. 478 - Begründung: Direkter Codebeleg der Feldübernahme.
|
||||
Prüfidee: Historieneintrag nach Versionswechsel abfragen und `Version`-Feld mit der tatsächlichen Belegversion zum Zeitpunkt der Erstellung vergleichen.
|
||||
Tracelinks: SyRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-04
|
||||
Titel: InvoiceBL.CancelInvoice implementiert Storno als Versionierung + Status 3
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: InvoiceBL
|
||||
Vorbedingung: `asset != null`
|
||||
Fakt: `CancelInvoice(Invoice asset, AppUser currUser)`: `Invoice newAsset = CreateNewVersion(currUser, asset.I3D, out message); newAsset.State = 3; foreach (InvoiceItem item in newAsset.Positions) item.Quantity = 0; StoreAsset(newAsset, currUser);` (Z. 392–411).
|
||||
Aussage: Die Methode `CancelInvoice` soll in dieser Reihenfolge (1) eine neue Version erzeugen, (2) deren Status auf 3 setzen, (3) alle Positionsmengen auf 0 setzen und (4) die neue Version speichern.
|
||||
Ergebnis: Nach Aufruf existiert eine gespeicherte Rechnungsversion mit `State=3` und ausschließlich Positionen mit `Quantity=0`.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 392–411 - Begründung: Vollständiger Methodenkörper als direkter Beleg.
|
||||
Prüfidee: Siehe SyRS-03.
|
||||
Tracelinks: SyRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-05
|
||||
Titel: StateToStringConverter bildet State 1/2/3 auf Klartext ab
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: UI (WPF ValueConverter)
|
||||
Vorbedingung: Ein `int`-Wert wird an den Converter gebunden.
|
||||
Fakt: `Convert`: `item==1 → "offen"`, `item==2 → "abgeschlossen"`, `item==3 → "abgebrochen"`, sonst `""`; `ConvertBack` wirft `NotSupportedException`.
|
||||
Aussage: Der Converter soll ausschließlich die Werte 1, 2 und 3 in feste deutsche Klartexte übersetzen und für alle anderen Werte eine leere Zeichenkette liefern; eine Rückkonvertierung ist bewusst nicht unterstützt.
|
||||
Ergebnis: Werte außerhalb {1,2,3} erscheinen in der UI als leeres Feld statt eines Fehlers.
|
||||
Belege:
|
||||
- [PRIMÄR] src/shared/Centron.Controls/Converters/StateToStringConverter.cs, Z. 9–27 - Begründung: Vollständiger Klassencode als Beleg.
|
||||
Prüfidee: Converter mit Werten 0,1,2,3,4 aufrufen und exakte Rückgabewerte prüfen.
|
||||
Tracelinks: SyRS-04
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-06
|
||||
Titel: AutomaticFacturaBL Suchmethoden für abrechnungsfähige Belege
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: AutomaticFacturaBL
|
||||
Vorbedingung: DAOSession ist initialisiert; abhängige BL-Instanzen (`OrderBL`, `InvoiceBL`, `ContractBL`, `HelpdeskBL` u. a.) sind über den Konstruktor injiziert.
|
||||
Fakt: Methodensignaturen `IList<DeliveryListCompact> SearchBillingDeliveryLists(DateTime endDate, int customerI3D)` (Z. 102), `IEnumerable<OrderCompact> SearchBillingOrders(DateTime endDate, int customerI3D, bool searchForInvoice = true)` (Z. 114), `IList<AutomaticFacturaCustomer> SearchCustomers(DateTime BilledTo)` (Z. 451).
|
||||
Aussage: Die Klasse `AutomaticFacturaBL` soll für Lieferscheine, Aufträge und Kunden je eigene, typisierte Suchmethoden mit Stichtags- und optionalem Kundenparameter bereitstellen.
|
||||
Ergebnis: Aufrufer erhalten typsichere Compact-DTOs statt roher Entitäten für die Batch-Verarbeitung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs, Z. 97–129, 448–460 - Begründung: Direkte Methodensignaturen und Klassenkommentare.
|
||||
Prüfidee: Siehe SyRS-05.
|
||||
Tracelinks: SyRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-07
|
||||
Titel: ContractBL.BillingIntervalKinds steuert Intervallberechnung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: ContractBL
|
||||
Vorbedingung: `contract.Beginn`, `contract.LaufzeitArt`, `contract.LaufzeitDauer` sind gesetzt.
|
||||
Fakt: `switch`-Anweisung mit Fällen `(int)BillingIntervalKinds.Monthly` (Z. 1021), `.Yearly` (Z. 1024), `.Quarterly` (Z. 1027); Aufruf `GetNewDate(contract.Beginn.Value, contract.LaufzeitArt.Value, contract.LaufzeitDauer.Value)` (Z. 1093) nach bestandener Null-Prüfung (Z. 1086).
|
||||
Aussage: Die Methode, die das nächste Laufzeitende berechnet, soll für jede der drei Intervallarten einen eigenen Berechnungspfad durchlaufen und nur bei vollständigen Eingabedaten ausgeführt werden.
|
||||
Ergebnis: Für jede Intervallart wird ein spezifisch berechnetes Datum zurückgegeben; bei unvollständigen Daten erfolgt kein Berechnungsversuch.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs, Z. 1021–1027, 1086–1093 - Begründung: Direkter Codebeleg von Verzweigung und Vorbedingungsprüfung.
|
||||
Prüfidee: Siehe SyRS-06.
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-08
|
||||
Titel: NamedQuery-Verknüpfung Vertragslaufzeit zu Rechnungs-/Gutschriftposition
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: ContractBL, NamedQueryAccess
|
||||
Vorbedingung: Eine Rechnungs- oder Gutschriftposition ist einem Vertrag zugeordnet.
|
||||
Fakt: `GetContractBillingPeriodForInvoiceItem(int invoiceItemI3D, BookKeepingReceiptKind receiptKind)` führt je nach `receiptKind` entweder `NamedQueryEnums.Asset.GetContractBillingPeriodForInvoiceItem` oder `...ForCreditVoucherItem` aus (Z. 324–335).
|
||||
Aussage: Die Methode soll abhängig vom übergebenen Belegtyp (Rechnung/Gutschrift) die jeweils passende Named Query zur Ermittlung des Abrechnungszeitraums auswählen.
|
||||
Ergebnis: Für Rechnungspositionen und Gutschriftpositionen wird jeweils die korrekte, typspezifische Datenbankabfrage verwendet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs, Z. 324–335 - Begründung: Direkter Codebeleg der Verzweigung nach `receiptKind`.
|
||||
Prüfidee: Aufruf mit `receiptKind=Invoice` und `receiptKind=CreditVoucher` und Vergleich der jeweils ausgeführten Named Query (z. B. per SQL-Profiler).
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-09
|
||||
Titel: TimerBillingSettingsPageViewModel.ReceiptKind löst Neuberechnung aus
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: TimerBillingSettingsPageViewModel
|
||||
Vorbedingung: Der Benutzer ändert die Auswahl des Zielbelegtyps in der UI.
|
||||
Fakt: Setter von `ReceiptKind`: `if (this.SetProperty(ref this._receiptKind, value, nameof(this.ReceiptKind))) this.UpdateBillingDateIsEnabled();` (Commit baa9e7bd9b).
|
||||
Aussage: Der Setter soll `UpdateBillingDateIsEnabled()` genau dann aufrufen, wenn sich der Wert von `ReceiptKind` tatsächlich geändert hat (`SetProperty` liefert `true`).
|
||||
Ergebnis: Ein erneutes Setzen desselben Werts löst keine unnötige Neuberechnung aus.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs (Diff aus Commit baa9e7bd9b) - Begründung: Direkter Codebeleg des bedingten Aufrufs.
|
||||
Prüfidee: `ReceiptKind` zweimal auf denselben Wert setzen und prüfen, dass `UpdateBillingDateIsEnabled()` nur beim ersten (wertändernden) Aufruf ausgeführt wird.
|
||||
Tracelinks: SyRS-07
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-10
|
||||
Titel: UpdateBillingDateIsEnabled liest ReceiptSettings-Konfigurationsschalter
|
||||
Ebene: SwRS
|
||||
Typ: nicht-funktional (Sicherheit/Konfigurierbarkeit)
|
||||
Akteur: TimerBillingSettingsPageViewModel, CentronCache
|
||||
Vorbedingung: `UseBillingDate == true`
|
||||
Fakt: `this.BillingDateIsEnabled = ReceiptKind == CentronObjectKindNumeric.InvoiceClass ? CentronCache.Instance.ReceiptSettings?.CanChangeDateInInvoices ?? false : CentronCache.Instance.ReceiptSettings?.CanChangeDateInDeliveryLists ?? false;` gefolgt von `ShowBillingDateNoteEnabledInfo = !BillingDateIsEnabled;` und ggf. Hinweistext-Erzeugung mit belegtyp-abhängigem Teilsatz („der Rechnung“/„des Lieferscheins“).
|
||||
Aussage: Die Methode soll bei fehlender oder nicht ladbarer `ReceiptSettings`-Konfiguration (`null`) sicherheitshalber `false` (Feld deaktiviert) annehmen und nicht `true`.
|
||||
Ergebnis: Ein Konfigurationsfehler (z. B. `ReceiptSettings == null`) führt zu einem gesperrten, nicht zu einem versehentlich freigegebenen Datumsfeld.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, Z. 566–588 - Begründung: Direkter Codebeleg inkl. Null-safe-Operator mit Fail-Closed-Default (`?? false`).
|
||||
Prüfidee: Siehe SyRS-08.
|
||||
Tracelinks: SyRS-08
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-11
|
||||
Titel: AppRightsBL.HasUserRight nutzt Session-Cache
|
||||
Ebene: SwRS
|
||||
Typ: nicht-funktional (Performanz-Effizienz)
|
||||
Akteur: AppRightsBL
|
||||
Vorbedingung: `appUserI3D` und `rightID` sind bekannt.
|
||||
Fakt: `return this.Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", () => GetAllAppRightsFromUser(appUserI3D)).Contains(rightID);` (Z. 644–649).
|
||||
Aussage: Die Methode soll die vollständige Rechteliste eines Benutzers höchstens einmal je Cache-Schlüssel aus der Datenbank laden und nachfolgende Prüfungen aus dem Cache bedienen.
|
||||
Ergebnis: Mehrfache `HasUserRight`-Aufrufe für denselben Benutzer innerhalb der Cache-Lebensdauer verursachen nur eine Datenbankabfrage.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 644–649 - Begründung: Direkter Codebeleg des Cache-Zugriffsmusters.
|
||||
Prüfidee: Zwei aufeinanderfolgende `HasUserRight`-Aufrufe für denselben Benutzer per SQL-Profiler beobachten; es darf nur eine `Sichtrus`/`Sichmemb`-Abfrage anfallen.
|
||||
Tracelinks: SyRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-12
|
||||
Titel: GetAllAppRightsFromUser: Raw-SQL gegen Sichtrus/Sichmemb
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: AppRightsBL
|
||||
Vorbedingung: `appUserI3D` bekannt.
|
||||
Fakt: `SELECT st.Recht AS ID FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D` (Z. 653–656), ausgeführt über `Session.Advanced.RawSqlAccess.ExecuteQuery<CustomClass>`.
|
||||
Aussage: Die Methode soll alle Rechte eines Benutzers über einen Inner Join zwischen Gruppen-Rechte-Tabelle (`Sichtrus`) und Gruppen-Mitgliedschaftstabelle (`Sichmemb`) ermitteln.
|
||||
Ergebnis: Die Rückgabemenge enthält genau die Recht-IDs, die einer der Gruppen zugeordnet sind, denen der Benutzer angehört.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 651–664 - Begründung: Direktes SQL-Statement als Beleg der Datenbankstruktur.
|
||||
Prüfidee: SQL direkt gegen Testdatenbestand ausführen und Ergebnis mit erwarteten Gruppenrechten abgleichen.
|
||||
Tracelinks: SyRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-13
|
||||
Titel: GetRightsFromCurrentUser aggregiert und dedupliziert Gruppenrechte
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: AppRightsBL
|
||||
Vorbedingung: `user.Groups != null`
|
||||
Fakt: `foreach (AppGroup group in user.Groups) { if (group.Rights != null) rights.AddRange(group.Rights); } rights = rights.Distinct().ToList(); rights.Remove(null);` (Z. 71–86); zusätzlich Reload über `Session.GetSession().Get<AppUser>(user.I3D)`, falls das übergebene Objekt nicht Teil der aktuellen Session ist (Z. 68–69).
|
||||
Aussage: Die Methode soll sicherstellen, dass das `AppUser`-Objekt Teil der aktuellen NHibernate-Session ist, bevor auf `Groups` zugegriffen wird, um Lazy-Loading-Fehler zu vermeiden.
|
||||
Ergebnis: Auch ein sessionsfremdes `AppUser`-Objekt wird korrekt nachgeladen, bevor die Rechteaggregation erfolgt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 63–87 - Begründung: Direkter Codebeleg inkl. Session-Reload-Absicherung.
|
||||
Prüfidee: Methode mit einem `AppUser`-Objekt aus einer bereits geschlossenen/fremden Session aufrufen und prüfen, dass kein `LazyInitializationException` auftritt.
|
||||
Tracelinks: SyRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-14
|
||||
Titel: CentronChecklistWebserviceBL: IsAdmin()-Bypass konkreter Endpunkte
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: CentronChecklistWebserviceBL
|
||||
Vorbedingung: Benutzer ist Mitglied der Administratorgruppe.
|
||||
Fakt: Z. 87: `if (loggedInUser.User.IsAdmin()) return true;` Z. 160: `if (loggedInUser.User.IsAdmin() || loggedInUser.User.HasUserRight(UserRightsConst.Administration.SETTINGS)) return (true, string.Empty);`
|
||||
Aussage: Die betroffenen Methoden sollen für Administratoren unabhängig vom Ergebnis der jeweiligen Einzelrechtprüfung Zugriff gewähren.
|
||||
Ergebnis: Ein Administrator ohne explizites Recht `Administration.SETTINGS` erhält dennoch `true`/Zugriff an diesen zwei Stellen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/WebServices/CheckListArea/CentronChecklistWebserviceBL.cs, Z. 87, 160 - Begründung: Direkter Codebeleg.
|
||||
Prüfidee: Siehe SyRS-11.
|
||||
Tracelinks: SyRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-15
|
||||
Titel: UserRightsExt.IsAdmin prüft Gruppennamen statt Gruppen-ID
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: UserRightsExt (Extension-Methode auf AppUser)
|
||||
Vorbedingung: `CurrUser.Groups` ist geladen.
|
||||
Fakt: `return CurrUser.Groups.Where(g => g.Name == UserRightsConst.ADMIN_ACCOUNT).FirstOrDefault() != null;` mit `ADMIN_ACCOUNT = "Administratoren"` (String-Literal); Methode fängt alle Exceptions ab und liefert dann `false` (fail-closed).
|
||||
Aussage: Die Methode soll die Administrator-Eigenschaft eines Benutzers anhand des Gruppennamens „Administratoren“ bestimmen und bei jeder Ausnahme sicherheitshalber `false` zurückgeben.
|
||||
Ergebnis: Wird die Gruppe „Administratoren“ umbenannt, verliert die Anwendung ohne Codeänderung die Fähigkeit, Administratoren als solche zu erkennen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs, Z. 56–66 - Begründung: Direkter Codebeleg inkl. Try/Catch-Fail-Closed-Verhalten.
|
||||
- [KONTEXT] src/webservice/Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/UserRightsConst.cs, Z. 20 - Begründung: Definition der Konstante als deutschsprachiger String.
|
||||
Prüfidee: Gruppe „Administratoren“ in Testsystem umbenennen und prüfen, dass `IsAdmin()` für ehemalige Mitglieder anschließend `false` liefert.
|
||||
Tracelinks: SyRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (siehe Hypothesen.md H-01)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-16
|
||||
Titel: CheckWebRightsFromUser: SQL gegen WebAccountsRights
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: AppRightsBL
|
||||
Vorbedingung: `webAccountI3D` und Liste zu prüfender Recht-IDs bekannt.
|
||||
Fakt: `SELECT WAR.WebRightsI3D AS ID FROM WebAccountsRights WAR WHERE WAR.WebAccountsI3D = :WebAccountI3D AND WAR.WebRightsI3D IN (:WebRightI3Ds)` (Z. 115–119).
|
||||
Aussage: Die Methode soll Web-Rechte ausschließlich über die Tabelle `WebAccountsRights`, verknüpft über `WebAccountsI3D`, ermitteln.
|
||||
Ergebnis: Die Rückgabe enthält nur die tatsächlich diesem WebAccount zugeordneten Web-Recht-IDs aus der übergebenen Prüfmenge.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 113–120 - Begründung: Direktes SQL-Statement.
|
||||
Prüfidee: Siehe SyRS-12.
|
||||
Tracelinks: SyRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-17
|
||||
Titel: UserRightsExt.HasWebRight Extension-Methoden
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: WebAccount
|
||||
Vorbedingung: Ein `WebAccount`-Objekt liegt vor.
|
||||
Fakt: Zwei überladene Extension-Methoden `HasWebRight(this WebAccount, WebAccountRightsConst)` und `HasWebRight(this WebAccount, int)`, beide delegieren an `AppRightsBL.HasWebAccountRight` (Z. 34–47).
|
||||
Aussage: Die Extension-Methode soll sowohl typsichere Enum-Werte als auch rohe Integer-Rechte-IDs als Eingabeparameter zulassen.
|
||||
Ergebnis: Aufrufer können je nach Kontext die stärker typisierte oder die generische Variante verwenden; beide liefern identisches Verhalten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs, Z. 34–47 - Begründung: Direkter Codebeleg beider Überladungen.
|
||||
Prüfidee: Beide Überladungen mit äquivalenten Werten aufrufen und identisches Ergebnis prüfen.
|
||||
Tracelinks: SyRS-12
|
||||
Konsolidierung: Kandidat: zwei Überladungen mit identischer Delegationslogik — im Zielsystem ggf. auf eine generische Signatur reduzierbar.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-18
|
||||
Titel: InvoiceBL.GetInvoiceByFilter blockt fremde Kunden-I3D für WebAccounts
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: InvoiceBL
|
||||
Vorbedingung: `currentUser != null`
|
||||
Fakt: `if (currentUser != null && currentUser.IsWebAccountLogin && filter.CustomerI3D != currentUser.WebAccount.CustomerI3D) return new PagingList<InvoiceCompact>();` (Z. 437–438), vor jeder weiteren Verarbeitung des Filters.
|
||||
Aussage: Die Methode soll bei WebAccount-Logins mit abweichender Kunden-I3D im Filter sofort eine leere, aber valide `PagingList` zurückgeben, ohne die nachfolgende Suchlogik (inkl. Paging-Berechnung) auszuführen.
|
||||
Ergebnis: Es wird keine SQL-Abfrage mit fremder Kunden-I3D ausgeführt; die Antwortstruktur bleibt für den Aufrufer konsistent (kein Fehler, sondern leere Liste).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 435–458 - Begründung: Direkter Codebeleg der frühen Rückgabe vor Aufbau der Suchexpression.
|
||||
Prüfidee: Siehe SyRS-13.
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-19
|
||||
Titel: Musterhafte IsWebAccountLogin-Prüfung in weiteren Beleg-BL-Klassen
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: OfferBL, OrderBL, ContractBL, CreditVoucherBL, DeliveryListBL
|
||||
Vorbedingung: Entsprechende Suchmethode wird von einem WebAccount-Login aufgerufen.
|
||||
Fakt: Textsuche nach `IsWebAccountLogin` liefert Treffer in den genannten fünf Dateien zusätzlich zu `InvoiceBL.cs`; der genaue Code-Kontext je Fundstelle wurde nicht einzeln gelesen.
|
||||
Aussage: Es ist anzunehmen, dass diese Klassen ein zu `InvoiceBL.GetInvoiceByFilter` analoges Filtermuster implementieren.
|
||||
Ergebnis: (nicht abschließend verifiziert)
|
||||
Belege:
|
||||
- [SEKUNDÄR] Grep-Treffer „IsWebAccountLogin“ in OfferBL.cs, OrderBL.cs, ContractBL.cs, CreditVoucherBL.cs, DeliveryListBL.cs - Begründung: Belegt nur das Vorkommen des Bezeichners, nicht die exakte Ausprägung der Prüfung je Datei.
|
||||
Prüfidee: Jede der fünf Dateien einzeln öffnen und die konkrete Bedingung mit dem Muster aus SwRS-18 vergleichen.
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: Kandidat: siehe SyRS-13.
|
||||
Status: belegt; [HYPOTHESE] Detailausprägung je Datei nicht verifiziert (H-06)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-20
|
||||
Titel: TwoFactorAuthenticationBL.ValidateAuthenticationPin nutzt GoogleAuthenticator
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: TwoFactorAuthenticationBL
|
||||
Vorbedingung: Benutzer hat einen TOTP-Schlüssel hinterlegt.
|
||||
Fakt: `return Centron.Core.GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin(appUserTwoFactorAuthKeyResult.Data, authenticationPin) ? Result.AsSuccess() : Result.AsError("Die eingegebene PIN ist ungültig!");` (Z. 51–53); vorgelagert Prüfung auf leeren Schlüssel (Z. 46–49).
|
||||
Aussage: Die Methode soll zunächst prüfen, ob überhaupt ein Schlüssel hinterlegt ist, und erst danach die eigentliche TOTP-Validierung über die interne `GoogleAuthenticator`-Bibliothek durchführen.
|
||||
Ergebnis: Ohne hinterlegten Schlüssel wird eine spezifische Fehlermeldung zurückgegeben, ohne dass `ValidatePin` mit leerem Schlüssel aufgerufen wird.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Z. 43–54 - Begründung: Direkter Codebeleg der Reihenfolge Prüfung→Validierung.
|
||||
Prüfidee: Aufruf mit leerem Schlüssel prüft spezifische Fehlermeldung; Aufruf mit korrektem/falschem TOTP-Code prüft jeweiliges Ergebnis.
|
||||
Tracelinks: SyRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-21
|
||||
Titel: NamedQueryEnums.PasswordManager für 2FA-Schlüsselverwaltung
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: TwoFactorAuthenticationBL
|
||||
Vorbedingung: -
|
||||
Fakt: `GetAppUserTwoFactorAuthKey` nutzt `NamedQueryEnums.PasswordManager.GetAppUserTwoFactorAuthKey`; `UpdateAppUserTwoFactorAuthKey` nutzt `NamedQueryEnums.PasswordManager.UpdateAppUserTwoFactorAuthKey` (Z. 29–41, 56–74).
|
||||
Aussage: Lese- und Schreibzugriff auf den 2FA-Schlüssel sollen ausschließlich über benannte, vordefinierte Datenbankabfragen (Named Queries) erfolgen, nicht über dynamisch generiertes SQL.
|
||||
Ergebnis: Der Zugriffspfad auf den 2FA-Schlüssel ist auf zwei fest definierte Named Queries beschränkt und damit zentral auditierbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Z. 29–41, 56–74 - Begründung: Direkter Codebeleg der Named-Query-Verwendung.
|
||||
Prüfidee: Named Queries im Mapping/Query-Katalog auffinden und deren SQL-Text auf Plausibilität (korrekte Tabelle/Spalte) prüfen.
|
||||
Tracelinks: SyRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-22
|
||||
Titel: PdfSigningSettings-DTO und GetPdfSigningSettings
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: PdfSigningBL
|
||||
Vorbedingung: -
|
||||
Fakt: `PdfSigningSettings` mit `HasCertificate`, `TsaServerUrl`, `TsaServerUsername`, `TsaServerPassword`, `Reason`, `Location`; `GetPdfSigningSettings()` befüllt dieses DTO aus `AppSettingsBL.GetSettings(...)` und entschlüsselt das TSA-Passwort bei Bedarf (Z. 29–55).
|
||||
Aussage: Die Methode soll alle sechs genannten Felder in einem Aufruf konsistent befüllen und dabei ein verschlüsselt gespeichertes Passwort transparent entschlüsseln.
|
||||
Ergebnis: Der Aufrufer erhält ein vollständiges, entschlüsseltes Einstellungsobjekt ohne selbst Entschlüsselungslogik implementieren zu müssen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 29–55 - Begründung: Direkter Codebeleg.
|
||||
Prüfidee: Siehe SyRS-15.
|
||||
Tracelinks: SyRS-15
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-23
|
||||
Titel: SavePdfSigningSettings prüft Recht Administration.SETTINGS
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: PdfSigningBL
|
||||
Vorbedingung: Benutzer ruft `SavePdfSigningSettings` auf.
|
||||
Fakt: `if (!currentUser.HasUserRight(UserRightsConst.Administration.SETTINGS)) return Result.AsError("Benutzer hat nicht die erforderlichen Rechte.", DefaultMessageCodes.RightCheckFailed);` (Z. 60–64), vor jeder Verarbeitung der übergebenen Einstellungen.
|
||||
Aussage: Die Methode soll die Rechteprüfung als ersten Schritt durchführen, bevor irgendeine der übergebenen Einstellungen gelesen oder verändert wird.
|
||||
Ergebnis: Ohne das Recht wird keine der Folgeoperationen (Verschlüsselung, Persistierung) ausgeführt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 57–64 - Begründung: Direkter Codebeleg der Reihenfolge.
|
||||
Prüfidee: Siehe SyRS-16.
|
||||
Tracelinks: SyRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-24
|
||||
Titel: PdfSigningBL verschlüsselt Zertifikat, Zertifikatspasswort und TSA-Passwort
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: PdfSigningBL, AESCryptoLogic
|
||||
Vorbedingung: `certificate != null` bzw. `settings.TsaServerPassword` nicht leer.
|
||||
Fakt: `certificateString = _cryptoLogic.EncryptText(certificateString); ... certPassString = _cryptoLogic.EncryptText(password); ...` (Z. 86–91); `crypted = _cryptoLogic.EncryptText(settings.TsaServerPassword);` (Z. 98–100); Reset-Fall löscht beide Werte auf `null` statt sie zu verschlüsseln (Z. 77–81).
|
||||
Aussage: Die Methode soll Zertifikatsdaten und beide Passwörter ausnahmslos vor der Übergabe an `UpdateLargeString`/`UpdateString` verschlüsseln; im Reset-Fall sollen die gespeicherten Werte vollständig entfernt (nicht nur überschrieben) werden.
|
||||
Ergebnis: In der Konfigurationsspeicherung liegt zu keinem Zeitpunkt ein Klartextwert für Zertifikat oder Passwörter vor.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 77–100 - Begründung: Direkter Codebeleg beider Pfade (Reset vs. Neuwert).
|
||||
Prüfidee: Siehe SyRS-17.
|
||||
Tracelinks: SyRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-25
|
||||
Titel: HelpdeskState/HelpdeskStateBase Feldstruktur
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: HelpdeskState-Entität
|
||||
Vorbedingung: -
|
||||
Fakt: `HelpdeskState : HelpdeskStateBase` mit `Icon` (byte[]), `IsDeactivated` (bool?), `IsInternalCompanyBillingActive` (bool?), `ServiceBoardWebColor` (string), `ServiceBoardWebIcon` (string) (Z. 8–14). Basisklasse `HelpdeskStateBase` selbst wurde nicht im Detail gelesen.
|
||||
Aussage: Die Klasse soll die genannten fünf Felder als eigene, von der Basisklasse unabhängige Erweiterung bereitstellen.
|
||||
Ergebnis: Diese Felder stehen für jeden Ticketstatus zur individuellen Pflege zur Verfügung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskState.cs, Z. 1–16 - Begründung: Direkte Felddeklaration.
|
||||
Prüfidee: Siehe SyRS-18.
|
||||
Tracelinks: SyRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-26
|
||||
Titel: ShowHelpdeskRight-Enum-Definition
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Rechtekonzept Helpdesk
|
||||
Vorbedingung: -
|
||||
Fakt: `public enum ShowHelpdeskRight { None, OnlyOwn, OnlyOwnAndNotify, All, OnlyOwnBranch }` (vollständiger Inhalt der Datei).
|
||||
Aussage: Das Enum soll exakt diese fünf, nicht kombinierbaren (kein `[Flags]`) Ausprägungen bereitstellen.
|
||||
Ergebnis: Einem Benutzer kann genau eine der fünf Stufen zugeordnet werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Helpdesks/ShowHelpdeskRight.cs, Z. 1–10 - Begründung: Vollständiger Dateiinhalt als Beleg.
|
||||
Prüfidee: Siehe SyRS-19.
|
||||
Tracelinks: SyRS-19
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE] Auswertungsstelle nicht verifiziert (H-02)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-27
|
||||
Titel: ArticleBL SQL-Fallunterscheidung BarcodeScanen
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: ArticleBL
|
||||
Vorbedingung: -
|
||||
Fakt: `... CASE WHEN A.BarcodeScanen = 1 THEN dbo.cfn_BarcodeCount(A.I3D,0) ELSE ISNULL((SELECT SUM(ISNULL(NA.Bestand,0)) FROM NebenlagerArtikel NA WHERE NA.ArtikelI3D = A.I3D),0) END` (Z. 2783).
|
||||
Aussage: Die Abfrage soll für `BarcodeScanen=1`-Artikel die Datenbankfunktion `cfn_BarcodeCount` und für alle übrigen Artikel die Summe des Feldes `Bestand` aus `NebenlagerArtikel` verwenden, wobei `NULL`-Werte jeweils als 0 behandelt werden (`ISNULL`).
|
||||
Ergebnis: Der berechnete Bestandswert ist nie `NULL`, auch wenn einzelne Datensätze `NULL` enthalten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Z. 2783 - Begründung: Direktes SQL-Fragment.
|
||||
Prüfidee: Siehe SyRS-20.
|
||||
Tracelinks: SyRS-20
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-28
|
||||
Titel: CustomerAssetBL.GetNewAsset übernimmt CustomerFinanceInfo
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: CustomerAssetBL<T,V>
|
||||
Vorbedingung: `objAsset.Customer` ist gesetzt.
|
||||
Fakt: `CustomerFinanceInfo financeInfo = this._customerBL.GetCustomerFinanceInformation(objAsset.Customer.I3D); objAsset.IgnoreDiscount = financeInfo.DontShowRabateText; objAsset.ExclusiveOfVAT = financeInfo.VATNotActive; objAsset.Discount = Convert.ToDouble(financeInfo.Discount); objAsset.Currency = objAsset.Country; objAsset.CurrencyFactor = objAsset.Currency.CurrencyRate; objAsset.PaymentCondition = this._assetConditionBL.TryGetAssetConditionById(financeInfo.PaymentConditionInvoiceI3D);` gefolgt von Fallback auf `AppSettingsConst.DefaultCustomerInvoicePaymentCondition` (Z. 136–150).
|
||||
Aussage: Die Methode soll bei fehlender kundenspezifischer Zahlungsbedingung (`TryGetAssetConditionById` liefert `null`) automatisch auf die global konfigurierte Standard-Zahlungsbedingung zurückgreifen, sofern eine solche > 0 konfiguriert ist.
|
||||
Ergebnis: `objAsset.PaymentCondition` ist entweder die kundenspezifische oder die global konfigurierte Standardbedingung, oder bleibt `null`, wenn keine von beiden vorhanden ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/CustomerAssetBL.cs, Z. 126–150 - Begründung: Direkter Codebeleg der Übernahme- und Fallback-Kette.
|
||||
Prüfidee: Siehe SyRS-21.
|
||||
Tracelinks: SyRS-21
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-29
|
||||
Titel: InvoiceBL.SetReminderDate berechnet ReminderDate ohne Persistierung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: InvoiceBL
|
||||
Vorbedingung: -
|
||||
Fakt: `var setting = ... .GetInt(AppSettingsConst.InvoiceReminderDays); if (setting == null) return; if (setting.Value > 0) { asset.ReminderDate = DateTime.Today.AddDays(setting ?? 0); }` (Z. 417–427); XML-Dokumentationskommentar: „Does not save the entity“.
|
||||
Aussage: Die Methode soll bei `setting == null` sofort zurückkehren und `ReminderDate` nur bei einem positiven Tageswert setzen, ohne den Beleg selbst zu speichern.
|
||||
Ergebnis: Ein Aufrufer muss den Beleg nach diesem Aufruf explizit selbst speichern, damit die Änderung persistiert wird.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 413–427 - Begründung: Direkter Codebeleg inkl. Dokumentationskommentar.
|
||||
Prüfidee: Siehe SyRS-22.
|
||||
Tracelinks: SyRS-22
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-30
|
||||
Titel: UserRightAuthorizationFilter: 401/403-Unterscheidung
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: UserRightAuthorizationFilter (IAuthorizationFilter)
|
||||
Vorbedingung: Request trifft auf annotierten Endpunkt.
|
||||
Fakt: `if (currentUser == null) { context.Result = new UnauthorizedResult(); return; } if (!_requiredRightId.HasValue || !currentUser.HasUserRight(_requiredRightId.Value)) context.Result = new ForbidResult();` (Z. 38–56).
|
||||
Aussage: Der Filter soll bei fehlendem Benutzer sofort mit 401 abbrechen (`return`) und andernfalls bei fehlendem oder nicht gesetztem Recht mit 403 antworten.
|
||||
Ergebnis: Ein Endpunkt ohne gesetzte `_requiredRightId` (theoretisch möglich, da `int?`) ist für jeden angemeldeten Benutzer gesperrt (`!_requiredRightId.HasValue` → 403).
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs, Z. 38–56 - Begründung: Direkter Codebeleg.
|
||||
Prüfidee: Siehe SyRS-23.
|
||||
Tracelinks: SyRS-23
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-31
|
||||
Titel: AnyUserRightAuthorizationFilter/AllUserRightsAuthorizationFilter: Fail-Closed bei leerer Liste
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: AnyUserRightAuthorizationFilter, AllUserRightsAuthorizationFilter
|
||||
Vorbedingung: Endpunkt mit `[AuthorizeAnyUserRight()]`/`[AuthorizeAllUserRights()]` ohne oder mit Rechte-Argumenten.
|
||||
Fakt: Beide Filter: `if (_requiredRightIds.Length == 0 || !hasAnyRight/!hasAllRights) context.Result = new ForbidResult();` (Any: Z. 52–53; All: Z. 52–53); `_requiredRightIds` wird bei `null`-Argument auf `Array.Empty<int>()` normalisiert (Konstruktor, Z. 33–36).
|
||||
Aussage: Beide Filter sollen ein leeres oder `null`-Rechte-Array als „kein Zugriff“ (403) behandeln, nicht als „uneingeschränkter Zugriff“.
|
||||
Ergebnis: Ein versehentlich ohne Argumente annotierter Endpunkt (`[AuthorizeAnyUserRight()]`) ist für alle Benutzer gesperrt statt offen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeAnyUserRightAttribute.cs, Z. 33–58 und AuthorizeAllUserRightsAttribute.cs, Z. 33–58 - Begründung: Direkter Codebeleg des Fail-Closed-Verhaltens in beiden Klassen.
|
||||
Prüfidee: Siehe SyRS-24.
|
||||
Tracelinks: SyRS-24
|
||||
Konsolidierung: Kandidat: nahezu identischer Aufbau beider Filterklassen (siehe SyRS-24).
|
||||
Status: belegt
|
||||
```
|
||||
+440
@@ -0,0 +1,440 @@
|
||||
# System Requirements Specification (SyRS) — c-entron ERP
|
||||
|
||||
Ebene 2 von 3 (StRS → SyRS → SwRS) nach ISO/IEC/IEEE 29148:2018. Systemverhalten, Schnittstellen sowie nicht-funktionale Anforderungen, zugeordnet zu ISO/IEC 25010-Qualitätsmerkmalen wo zutreffend.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: SyRS-01
|
||||
Titel: Versionsverwaltung für Kundenbelege
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: Beleg-Businesslogik (AssetBL<T,V>)
|
||||
Vorbedingung: Ein Kundenbeleg mit Version ≥ 1 existiert.
|
||||
Fakt: `AssetBase` führt die Felder `Version`, `MaxVersion`, `OldVersion`, `IsNewVersion`; `AssetBL.CreateNewVersion(...)` ruft `DoBeforeCreateNewVersion` → `DoCreateNewVersion` (Version+=1, MaxVersion=Version, IsNewVersion=true) → `DoAfterCreateNewVersion` in fester Reihenfolge auf.
|
||||
Aussage: Das System soll jede Änderung an einem fixierten Kundenbeleg als dreiphasigen Versionierungsprozess (Vorbereitung, Versionserhöhung, Nachbereitung) mit konsistent geführten Versionsfeldern abbilden.
|
||||
Ergebnis: Nach Abschluss des Prozesses ist `Version` um 1 erhöht, `MaxVersion` synchron, `IsNewVersion=true`; Vorgängerversion bleibt unverändert bestehen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Z. 953–1032 (`CreateNewVersion`, `DoBeforeCreateNewVersion`, `DoCreateNewVersion`, `DoAfterCreateNewVersion`) - Begründung: Durchgesetzter, dreiphasiger Ablauf als Extension-Point-Muster (virtuelle Methoden für Spezialisierung je Belegart).
|
||||
Prüfidee: Sequenzieller Aufruf beobachten (z. B. per Log/Debugger) und prüfen, dass alle drei Phasen in der genannten Reihenfolge durchlaufen werden.
|
||||
Tracelinks: StRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-02
|
||||
Titel: Historisierung der Barcode-Positionszuordnung bei Versionswechsel
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: Beleg-Businesslogik
|
||||
Vorbedingung: Eine Belegposition ist mit einem oder mehreren Barcodes/Seriennummern verknüpft; der Beleg wird neu versioniert.
|
||||
Fakt: Beim Versionswechsel wird die Zuordnung Barcode→Position über `CurrentVersion` geführt (`BarcodeToPosition`); ein Historieneintrag übernimmt `objHistory.Version = pos.Owner.Version` (AssetBL.cs Z. 478).
|
||||
Aussage: Das System soll die Zuordnung von Barcodes/Seriennummern zu Belegpositionen je Version historisieren, damit nachvollziehbar bleibt, welcher Barcode zu welcher Belegversion gehörte.
|
||||
Ergebnis: Für jede Belegversion existiert ein eigener, versionsbezogener Historieneintrag der Barcode-Positions-Zuordnung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs, Z. 337–402 (Prüfung `activeBinding.CurrentVersion == ...`) und Z. 478 (`objHistory.Version = pos.Owner.Version`) - Begründung: Durchgesetzte Versionsbindung der Barcode-Zuordnung.
|
||||
Prüfidee: Beleg mit gebundenem Barcode neu versionieren und prüfen, dass ein Historieneintrag mit der alten Versionsnummer erhalten bleibt.
|
||||
Tracelinks: StRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-03
|
||||
Titel: Storno-Prozess erzeugt neue Version mit Status „abgebrochen“
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: Beleg-Businesslogik (Invoice)
|
||||
Vorbedingung: Eine Rechnung im Status „offen“ oder „abgeschlossen“ soll storniert werden.
|
||||
Fakt: `InvoiceBL.CancelInvoice` ruft `CreateNewVersion` auf, setzt auf der neuen Version `State=3` und iteriert über `newAsset.Positions`, um `item.Quantity = 0` zu setzen, bevor `StoreAsset` gespeichert wird.
|
||||
Aussage: Das System soll den Stornoprozess einer Rechnung als Spezialfall der allgemeinen Versionierung umsetzen: neue Version anlegen, Status auf „abgebrochen“ setzen, Positionsmengen auf 0 zurücksetzen.
|
||||
Ergebnis: Es entsteht eine neue, gespeicherte Rechnungsversion mit State=3 und Positionsmengen=0.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 392–411 - Begründung: Vollständiger, durchgesetzter Ablauf des Stornoprozesses in einer Methode.
|
||||
Prüfidee: `CancelInvoice` aufrufen und Rückgabewert von `StoreAsset` sowie den persistierten Datensatz prüfen (State=3, alle Positionsmengen=0).
|
||||
Tracelinks: StRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-04
|
||||
Titel: Einheitlicher Belegstatus-Wertebereich für Kundenbelege
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System, UI
|
||||
Vorbedingung: Ein Kundenbeleg besitzt ein `State`-Feld (Integer).
|
||||
Fakt: `StateToStringConverter` bildet den Integer-Wert von `State` auf die Zeichenketten „offen“ (1), „abgeschlossen“ (2), „abgebrochen“ (3) ab; unbekannte Werte liefern eine leere Zeichenkette.
|
||||
Aussage: Das System soll für den Belegstatus einen festen, dreiwertigen Wertebereich (1=offen, 2=abgeschlossen, 3=abgebrochen) verwenden und in der Oberfläche konsistent beschriften.
|
||||
Ergebnis: Jeder in der UI angezeigte Belegstatus lässt sich eindeutig einem der drei Werte zuordnen; Werte außerhalb 1–3 werden nicht sprechend dargestellt.
|
||||
Belege:
|
||||
- [SEKUNDÄR] src/shared/Centron.Controls/Converters/StateToStringConverter.cs, Z. 9–21 - Begründung: UI-Beleg für die fachliche Bedeutung der drei Statuswerte; kein DB-Constraint gefunden, das den Wertebereich technisch erzwingt (siehe Hypothesen.md H-03).
|
||||
Prüfidee: `State`-Werte 1, 2, 3 und z. B. 4 an der UI anzeigen lassen und die jeweilige Beschriftung/leere Anzeige prüfen.
|
||||
Tracelinks: StRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-05
|
||||
Titel: Batch-Ermittlung abrechnungsfähiger Belege je Kunde/Stichtag
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: AutomaticFacturaBL
|
||||
Vorbedingung: Stichtag (`endDate`) und optional eine Kunden-I3D sind als Parameter bekannt.
|
||||
Fakt: `SearchBillingDeliveryLists(DateTime endDate, int customerI3D)` und `SearchBillingOrders(DateTime endDate, int customerI3D, bool searchForInvoice = true)` liefern IList/IEnumerable abrechnungsfähiger Belege; `SearchCustomers(DateTime BilledTo)` ermittelt die Kunden mit noch nicht abgerechneten Vorgängen.
|
||||
Aussage: Das System soll für einen gegebenen Stichtag und optional einen Kunden eine deterministische Liste abrechnungsfähiger Lieferscheine bzw. Aufträge liefern, die als Grundlage für automatisiert erzeugte Rechnungen dient.
|
||||
Ergebnis: Die zurückgegebene Liste enthält ausschließlich Belege mit Datum ≤ Stichtag, die noch keiner Rechnung zugeordnet sind.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs, Z. 102, 114, 451 (Methodensignaturen) - Begründung: Durchgesetzte Schnittstellen der Batch-Ermittlung.
|
||||
Prüfidee: Zwei Lieferscheine (vor/nach Stichtag) für denselben Kunden anlegen und prüfen, dass nur der Beleg vor dem Stichtag zurückgegeben wird.
|
||||
Tracelinks: StRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-06
|
||||
Titel: Turnusberechnung für Vertragsabrechnung
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: ContractBL
|
||||
Vorbedingung: Vertrag mit `Beginn`, `LaufzeitArt`, `LaufzeitDauer` ist gesetzt (nicht null).
|
||||
Fakt: `ContractBL` verzweigt über `BillingIntervalKinds` (Monthly/Quarterly/Yearly) und berechnet über `GetNewDate(contract.Beginn.Value, contract.LaufzeitArt.Value, contract.LaufzeitDauer.Value)` das nächste Laufzeitende; bei `contract.Beginn == null || contract.LaufzeitArt == null || contract.LaufzeitDauer == null` wird die Berechnung nicht durchgeführt (Z. 1086).
|
||||
Aussage: Das System soll das nächste Abrechnungs-/Laufzeitende eines Vertrags ausschließlich berechnen, wenn Beginn, Laufzeitart und Laufzeitdauer vollständig gepflegt sind, und dabei die drei Intervallarten (monatlich/quartalsweise/jährlich) unterschiedlich behandeln.
|
||||
Ergebnis: Bei vollständigen Vertragsdaten liefert das System ein korrektes nächstes Datum; bei unvollständigen Daten unterbleibt die Berechnung (kein Absturz, keine Datumsangabe).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs, Z. 1021–1027 (Intervall-Switch) und Z. 1086–1093 (Null-Prüfung + `GetNewDate`-Aufruf) - Begründung: Durchgesetzte Kontrollflusslogik inkl. Absicherung gegen unvollständige Vertragsdaten.
|
||||
Prüfidee: Vertrag mit `LaufzeitArt=null` anlegen und prüfen, dass keine Exception geworfen wird und kein Folgedatum berechnet wird.
|
||||
Tracelinks: StRS-04
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-07
|
||||
Titel: Auswahl des Zielbelegtyps für verdichtete Zeiterfassungen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: Fakturierung (UI: TimerBillingSettingsPageViewModel)
|
||||
Vorbedingung: Zeiterfassungen liegen vor; TimerBilling-Assistent ist geöffnet.
|
||||
Fakt: Die Property `ReceiptKind` vom Typ `CentronObjectKindNumeric` steuert, ob `InvoiceClass` oder `DeliveryListClass` als Zielbelegtyp gewählt wird; ein Wertwechsel löst `UpdateBillingDateIsEnabled()` aus.
|
||||
Aussage: Das System soll dem Benutzer die Wahl zwischen den Zielbelegtypen Rechnung und Lieferschein für die Verdichtung erfasster Zeiten anbieten und bei Auswahländerung abhängige UI-Zustände (Datumsänderbarkeit) automatisch aktualisieren.
|
||||
Ergebnis: Nach Auswahl eines Zielbelegtyps wird der zugehörige UI-Zustand (Datumsfeld aktiv/inaktiv, Hinweistext) neu berechnet.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, Property `ReceiptKind` (Setter ruft `UpdateBillingDateIsEnabled()` auf, Commit baa9e7bd9b) - Begründung: Durchgesetzte reaktive UI-Logik.
|
||||
Prüfidee: `ReceiptKind` von Invoice auf DeliveryList umstellen und beobachten, dass `BillingDateIsEnabled`/`ShowBillingDateNoteEnabledInfo` neu ausgewertet werden.
|
||||
Tracelinks: StRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-08
|
||||
Titel: Konfigurierbare Änderbarkeit des Abrechnungsdatums bei TimerBilling
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (Sicherheit/Konfigurierbarkeit)
|
||||
Akteur: System (CentronCache), UI
|
||||
Vorbedingung: `UseBillingDate=true` und ein Zielbelegtyp ist gewählt.
|
||||
Fakt: `UpdateBillingDateIsEnabled()` setzt `BillingDateIsEnabled` abhängig von `CentronCache.Instance.ReceiptSettings.CanChangeDateInInvoices` (bei ReceiptKind=Invoice) bzw. `.CanChangeDateInDeliveryLists` (bei DeliveryList); bei deaktivierter Einstellung wird ein Hinweistext „Sie besitzen nicht das Recht ... Datum ... zu ändern“ angezeigt.
|
||||
Aussage: Das System soll die Änderbarkeit des Abrechnungsdatums bei TimerBilling getrennt für Rechnungen und Lieferscheine über eine zentrale Einstellung steuern und dem Benutzer bei fehlender Freigabe einen erklärenden Hinweis anzeigen.
|
||||
Ergebnis: Ist die jeweilige Einstellung deaktiviert, ist das Datumsfeld read-only und ein Hinweistext wird eingeblendet; andernfalls ist es editierbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/centron/Centron.WPF.UI/Modules/Finances/TimerBilling/Pages/TimerBillingSettingsPageViewModel.cs, Methode `UpdateBillingDateIsEnabled()` Z. 566–588 - Begründung: Durchgesetzte, vollständige Fallunterscheidung inkl. Hinweistext-Generierung.
|
||||
- [KONTEXT] Commit-Nachricht baa9e7bd9b spricht von einem „rights check“, der Code liest jedoch einen Konfigurationsschalter (`ReceiptSettings`), nicht `HasUserRight(...)` - Begründung: Diskrepanz zwischen Commit-Beschreibung und tatsächlicher Implementierung; siehe Hypothesen.md H-04.
|
||||
Prüfidee: `CanChangeDateInInvoices=false` setzen, ReceiptKind=Invoice wählen und prüfen, dass das Datumsfeld deaktiviert ist und der Hinweistext „... der Rechnung ...“ erscheint.
|
||||
Tracelinks: StRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE] ob dieser Schalter organisatorisch als „Recht“ oder als globale Einstellung geführt werden soll, ist zu klären (H-04).
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-09
|
||||
Titel: Rechteprüfung über Gruppenzugehörigkeit mit Session-Cache
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: AppRightsBL, DB (Sichtrus/Sichmemb)
|
||||
Vorbedingung: Ein Benutzer ist angemeldet und einer oder mehreren Gruppen zugeordnet.
|
||||
Fakt: `AppRightsBL.HasUserRight(int appUserI3D, int rightID)` liest die Rechteliste eines Benutzers per `Session.Advanced.Cache.GetOrAdd($"AllRightsFromAppUser{appUserI3D}", () => GetAllAppRightsFromUser(appUserI3D))` und prüft `rights.Contains(rightID)`; die zugrunde liegende SQL verknüpft `Sichtrus` (Recht↔Gruppe) und `Sichmemb` (Benutzer↔Gruppe).
|
||||
Aussage: Das System soll die Rechte eines Benutzers je Session cachen und bei jeder Rechteprüfung aus dem Cache statt erneut aus der Datenbank lesen, um wiederholte Datenbankzugriffe zu vermeiden.
|
||||
Ergebnis: Innerhalb derselben Session-Cache-Lebensdauer liefert eine Rechteprüfung ein konsistentes Ergebnis, auch wenn sich die Rechtezuordnung des Benutzers zwischenzeitlich in der Datenbank ändert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 644–664 (`HasUserRight`, `GetAllAppRightsFromUser`) - Begründung: Durchgesetzter Cache-Mechanismus inkl. SQL-Quelle.
|
||||
Prüfidee: Benutzer meldet sich an (Cache wird befüllt); Recht wird per Admin-Oberfläche entzogen; prüfen, ob und wann (gleiche Session/nach Neuanmeldung) `HasUserRight` das entzogene Recht noch als vorhanden meldet.
|
||||
Tracelinks: StRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE] Cache-Invalidierungsstrategie und Gültigkeitsdauer bei Rechteänderung zur Laufzeit wurden nicht ermittelt (H-05).
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-10
|
||||
Titel: Aggregation der Rechte eines Benutzers aus allen zugeordneten Gruppen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: AppRightsBL
|
||||
Vorbedingung: `AppUser.Groups` ist geladen (nicht null).
|
||||
Fakt: `GetRightsFromCurrentUser(AppUser user)` iteriert über `user.Groups`, sammelt `group.Rights` in einer Liste, entfernt Duplikate (`Distinct()`) und entfernt `null`-Einträge.
|
||||
Aussage: Das System soll die effektive Rechtemenge eines Benutzers als Vereinigungsmenge (ohne Duplikate) der Rechte aller ihm zugeordneten Gruppen berechnen.
|
||||
Ergebnis: Die zurückgegebene Liste enthält jedes Recht höchstens einmal, auch wenn mehrere Gruppen dasselbe Recht enthalten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 63–87 - Begründung: Durchgesetzte Aggregations- und Deduplizierungslogik.
|
||||
Prüfidee: Benutzer zwei Gruppen zuordnen, die ein gemeinsames Recht enthalten, und prüfen, dass es in der Ergebnisliste nur einmal vorkommt.
|
||||
Tracelinks: StRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-11
|
||||
Titel: Administratorgruppe umgeht Einzelrechtprüfungen in bestimmten Modulen
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: AppUser (Administratorgruppe)
|
||||
Vorbedingung: Benutzer ist Mitglied der Gruppe mit Namen „Administratoren“.
|
||||
Fakt: `IsAdmin()` prüft `CurrUser.Groups.Where(g => g.Name == UserRightsConst.ADMIN_ACCOUNT)`; in `CentronChecklistWebserviceBL.cs` wird dies an mehreren Stellen als alleinige oder ODER-verknüpfte Zugriffsbedingung verwendet.
|
||||
Aussage: Das System soll für Mitglieder der administrativ benannten Gruppe an den betroffenen, im Code identifizierten Stellen Zugriff gewähren, ohne die granulare Einzelrechtprüfung zu durchlaufen.
|
||||
Ergebnis: Ein Administrator erhält Zugriff auf die betroffene Funktion, auch ohne das spezifische Einzelrecht.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/WebServices/CheckListArea/CentronChecklistWebserviceBL.cs, Z. 87, 160 - Begründung: Konkrete, durchgesetzte Bypass-Stellen.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs, Z. 56–66 (`IsAdmin()`) - Begründung: Zentrale Definition, von der der Bypass abhängt.
|
||||
Prüfidee: Siehe StRS-07.
|
||||
Tracelinks: StRS-07
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-12
|
||||
Titel: Separates Rechtemodell für Web-Accounts
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: WebAccount, AppRightsBL
|
||||
Vorbedingung: Ein WebAccount-Datensatz existiert.
|
||||
Fakt: `CheckWebRightsFromUser(int webAccountI3D, IList<int> webRights)` fragt die Tabelle `WebAccountsRights` ab (`SELECT WAR.WebRightsI3D FROM WebAccountsRights WAR WHERE WAR.WebAccountsI3D = :WebAccountI3D AND WAR.WebRightsI3D IN (...)`); dies ist eine eigene Tabelle, unabhängig von `Sichtrus`/`Sichmemb`.
|
||||
Aussage: Das System soll Rechte für Kundenportal-Zugänge in einer eigenständigen Tabelle (`WebAccountsRights`) führen, getrennt von den internen Mitarbeiterrechten.
|
||||
Ergebnis: Eine Änderung an `Sichtrus`/`Sichmemb` hat keine Auswirkung auf `WebAccountsRights` und umgekehrt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Z. 113–120 - Begründung: Durchgesetzte, eigenständige SQL-Quelle für Web-Rechte.
|
||||
Prüfidee: Web-Recht für einen WebAccount setzen und prüfen, dass keine Zeile in `Sichtrus`/`Sichmemb` dafür angelegt wird.
|
||||
Tracelinks: StRS-08
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-13
|
||||
Titel: Serverseitige Filterung von Belegabfragen nach WebAccount-Kunde
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Beleg-Businesslogik, WebAccount
|
||||
Vorbedingung: Anfrage stammt von einem WebAccount-Login (`currentUser.IsWebAccountLogin == true`).
|
||||
Fakt: `InvoiceBL.GetInvoiceByFilter` (und laut Fundstellenmuster analog weitere Beleg-BL-Klassen) prüft vor Ausführung der eigentlichen Suche, ob `filter.CustomerI3D != currentUser.WebAccount.CustomerI3D`, und liefert in diesem Fall eine leere `PagingList` zurück, bevor die Datenbankabfrage überhaupt aufgebaut wird.
|
||||
Aussage: Das System soll bei WebAccount-Logins jede Belegabfrage serverseitig gegen die Kunden-I3D des angemeldeten WebAccounts validieren und bei Abweichung keine Daten zurückliefern, unabhängig von client-seitig übergebenen Filterwerten.
|
||||
Ergebnis: Ein manipulierter Filter mit fremder Kunden-I3D liefert für WebAccount-Logins stets ein leeres Ergebnis statt fremder Daten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 435–439 - Begründung: Durchgesetzte, frühe Rückgabe vor jeder DB-Abfrage.
|
||||
- [SEKUNDÄR] Musterfund `IsWebAccountLogin` in OfferBL.cs, OrderBL.cs, ContractBL.cs, CreditVoucherBL.cs, DeliveryListBL.cs - Begründung: Deutet auf identisches Muster hin, Einzelverifikation je Datei steht aus (siehe Analysebericht.md).
|
||||
Prüfidee: Siehe StRS-09.
|
||||
Tracelinks: StRS-09
|
||||
Konsolidierung: Kandidat: sechsfach dupliziertes Prüfmuster, siehe StRS-09.
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-14
|
||||
Titel: TOTP-Schlüsselverwaltung und serverseitige PIN-Validierung
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: TwoFactorAuthenticationBL
|
||||
Vorbedingung: Benutzer versucht, eine 2FA-PIN einzugeben.
|
||||
Fakt: Der TOTP-Schlüssel wird per NamedQuery `PasswordManager.GetAppUserTwoFactorAuthKey`/`UpdateAppUserTwoFactorAuthKey` gelesen/geschrieben; die eigentliche PIN-Prüfung erfolgt über `Centron.Core.GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin(key, pin)`.
|
||||
Aussage: Das System soll den TOTP-Schlüssel serverseitig persistieren und jede PIN-Prüfung serverseitig (nicht im Client) gegen diesen Schlüssel durchführen.
|
||||
Ergebnis: Eine clientseitig eingegebene PIN wird nur nach serverseitiger Validierung als korrekt akzeptiert; ohne hinterlegten Schlüssel ist keine erfolgreiche Prüfung möglich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Z. 43–74 - Begründung: Durchgesetzte Kette aus Schlüsselermittlung und Validierung.
|
||||
Prüfidee: Siehe StRS-10.
|
||||
Tracelinks: StRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-15
|
||||
Titel: Konfigurierbare PDF-Signatureinstellungen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: Administrator, PdfSigningBL
|
||||
Vorbedingung: Zertifikat und TSA-Zugangsdaten liegen vor oder sollen konfiguriert werden.
|
||||
Fakt: `PdfSigningSettings` (DTO) umfasst `HasCertificate`, `TsaServerUrl`, `TsaServerUsername`, `TsaServerPassword`, `Reason`, `Location`; diese werden über `AppSettingsBL` als Application Settings persistiert (`ApplicationSettingID.PdfSigning*`).
|
||||
Aussage: Das System soll alle für die digitale PDF-Signatur benötigten Parameter (Zertifikat, TSA-Server-Zugangsdaten, Signaturgrund, Signaturort) als zentrale, administrierbare Einstellungen bereitstellen.
|
||||
Ergebnis: Ein Administrator kann Zertifikat, TSA-Server und Signaturmetadaten ohne Codeänderung konfigurieren.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 29–55 (`GetPdfSigningSettings`) - Begründung: Vollständige, durchgesetzte Aufzählung der konfigurierbaren Signaturparameter.
|
||||
Prüfidee: Alle fünf Einstellungswerte setzen, Anwendung neu starten und prüfen, dass `GetPdfSigningSettings` dieselben Werte zurückliefert.
|
||||
Tracelinks: StRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-16
|
||||
Titel: Änderung der Signatureinstellungen nur mit Administrationsrecht
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator, PdfSigningBL
|
||||
Vorbedingung: Ein Benutzer versucht, `SavePdfSigningSettings` aufzurufen.
|
||||
Fakt: `SavePdfSigningSettings` prüft zu Beginn `if (!currentUser.HasUserRight(UserRightsConst.Administration.SETTINGS)) return Result.AsError("Benutzer hat nicht die erforderlichen Rechte.", DefaultMessageCodes.RightCheckFailed);` (Z. 60–64).
|
||||
Aussage: Das System soll das Ändern der PDF-Signatureinstellungen ausschließlich Benutzern mit dem Recht „Administration/Settings“ gestatten und andernfalls einen definierten Fehlercode zurückgeben.
|
||||
Ergebnis: Benutzer ohne dieses Recht erhalten `Result.AsError` mit Code `RightCheckFailed`; die Einstellungen werden nicht verändert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 57–64 - Begründung: Durchgesetzte, frühe Rechteprüfung vor jeder Zustandsänderung.
|
||||
Prüfidee: Benutzer ohne Recht „SETTINGS“ ruft `SavePdfSigningSettings` auf und erhält `Result.AsError` mit Code `RightCheckFailed`.
|
||||
Tracelinks: StRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-17
|
||||
Titel: AES-Verschlüsselung von TSA-Zugangsdaten und Zertifikatspasswort
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: PdfSigningBL, AESCryptoLogic
|
||||
Vorbedingung: Ein Zertifikat oder TSA-Passwort wird gespeichert oder gelesen.
|
||||
Fakt: Vor der Persistierung wird `_cryptoLogic.EncryptText(...)` auf Zertifikat, Zertifikatspasswort und TSA-Passwort angewendet; beim Lesen erfolgt `DecryptText(...)` auf das TSA-Passwort.
|
||||
Aussage: Das System soll alle Zugangsdaten im Zusammenhang mit der PDF-Signatur (Zertifikat, zugehöriges Passwort, TSA-Server-Passwort) ausschließlich AES-verschlüsselt persistieren.
|
||||
Ergebnis: In der Datenbank/Konfiguration liegt zu keinem Zeitpunkt ein Klartext-Passwort für Zertifikat oder TSA-Zugang vor.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Security/PdfSigningBL.cs, Z. 47–49, 86–91, 98–100 - Begründung: Durchgesetzte Ver-/Entschlüsselung an allen Speicher-/Lesepunkten.
|
||||
Prüfidee: Siehe StRS-18.
|
||||
Tracelinks: StRS-11, StRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-18
|
||||
Titel: Ticket-/Vorgangsstatus als editierbare Stammdatentabelle
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: Administrator, HelpdeskState-Entität
|
||||
Vorbedingung: Das Helpdesk-Modul ist aktiv.
|
||||
Fakt: `HelpdeskState : HelpdeskStateBase` erweitert die Basisklasse um `Icon` (byte[]), `IsDeactivated` (bool?), `IsInternalCompanyBillingActive` (bool?), `ServiceBoardWebColor`/`ServiceBoardWebIcon` (string).
|
||||
Aussage: Das System soll je Ticketstatus Icon, Deaktivierungsflag, Verrechnungsrelevanz sowie Farbe/Icon für ein Web-Serviceboard als eigene, persistente Attribute führen.
|
||||
Ergebnis: Jeder Ticketstatus-Datensatz kann individuell dargestellt, deaktiviert und hinsichtlich interner Verrechnung gekennzeichnet werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskState.cs, Z. 1–16 - Begründung: Vollständige Felddefinition der Stammdatenentität.
|
||||
Prüfidee: Siehe StRS-12.
|
||||
Tracelinks: StRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-19
|
||||
Titel: Fünfstufiges Sichtbarkeits-Scoping für Tickets
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Support-Mitarbeiter
|
||||
Vorbedingung: Einem Benutzer ist eine Ausprägung von `ShowHelpdeskRight` zugeordnet.
|
||||
Fakt: Enum `ShowHelpdeskRight { None, OnlyOwn, OnlyOwnAndNotify, All, OnlyOwnBranch }`.
|
||||
Aussage: Das System soll fünf Sichtbarkeitsstufen für Tickets unterscheiden: keine Sicht, nur eigene, nur eigene mit Benachrichtigung, alle, nur eigene Niederlassung.
|
||||
Ergebnis: Die Ticketliste eines Benutzers ist auf die gemäß seiner Stufe zulässige Teilmenge beschränkt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Helpdesks/ShowHelpdeskRight.cs, Z. 1–10 - Begründung: Vollständige Enum-Definition.
|
||||
Prüfidee: Siehe StRS-13.
|
||||
Tracelinks: StRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt; [HYPOTHESE] Auswertungsstelle nicht verifiziert (H-02)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-20
|
||||
Titel: Bestandsermittlung abhängig vom Artikel-Flag „BarcodeScanen“
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: ArticleBL
|
||||
Vorbedingung: Artikel mit gesetztem oder ungesetztem `BarcodeScanen`-Flag.
|
||||
Fakt: SQL-Fallunterscheidung: `BarcodeScanen = 1` → `dbo.cfn_BarcodeCount(A.I3D,0)`; sonst → `SUM(NA.Bestand)` aus `NebenlagerArtikel` je `ArtikelI3D`.
|
||||
Aussage: Das System soll den verfügbaren Bestand eines Artikels serverseitig (in der Datenbankfunktion/-abfrage) abhängig vom Artikel-Flag entweder durch Zählung erfasster Barcodes oder durch Summierung der Lagerbestandsmengen ermitteln.
|
||||
Ergebnis: Für `BarcodeScanen=1`-Artikel ist der gemeldete Bestand unabhängig vom `Bestand`-Feld in `NebenlagerArtikel`.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Z. 2783 - Begründung: Durchgesetzte, serverseitige SQL-Fallunterscheidung.
|
||||
Prüfidee: Siehe StRS-14.
|
||||
Tracelinks: StRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-21
|
||||
Titel: Übernahme kundenindividueller Finanzkonditionen bei Belegneuanlage
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: CustomerAssetBL
|
||||
Vorbedingung: Kunde mit `CustomerFinanceInfo` existiert; neuer Beleg wird für diesen Kunden angelegt.
|
||||
Fakt: `GetNewAsset` liest `CustomerFinanceInfo` per `_customerBL.GetCustomerFinanceInformation(objAsset.Customer.I3D)` und überträgt `Discount`, `VATNotActive`→`ExclusiveOfVAT`, `PaymentConditionInvoiceI3D`→`PaymentCondition`, `DontShowRabateText`→`IgnoreDiscount` in den neuen Beleg; fehlt eine Zahlungsbedingung, wird ein Default aus `AppSettingsConst.DefaultCustomerInvoicePaymentCondition` verwendet.
|
||||
Aussage: Das System soll beim Anlegen eines Belegkopfes zunächst versuchen, die kundenspezifische Zahlungsbedingung zu übernehmen, und nur bei deren Fehlen auf eine global konfigurierte Standard-Zahlungsbedingung zurückgreifen.
|
||||
Ergebnis: Der neue Beleg trägt entweder die kundenspezifische oder — als Fallback — die global konfigurierte Zahlungsbedingung; niemals bleibt das Feld unbegründet leer, solange ein Default konfiguriert ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/CustomerAssetBL.cs, Z. 126–150 - Begründung: Durchgesetzte Übernahme- und Fallback-Logik.
|
||||
Prüfidee: Siehe StRS-15.
|
||||
Tracelinks: StRS-15
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-22
|
||||
Titel: Automatische Erinnerungsdatum-Berechnung für Rechnungen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: InvoiceBL
|
||||
Vorbedingung: `AppSettingsConst.InvoiceReminderDays` ist konfiguriert (> 0).
|
||||
Fakt: `SetReminderDate(Invoice asset)` liest die Einstellung; ist sie null, wird die Methode ohne Änderung verlassen; ist sie > 0, wird `asset.ReminderDate = DateTime.Today.AddDays(setting)` gesetzt. Die Methode speichert den Beleg nicht selbst („Does not save the entity“, XML-Kommentar).
|
||||
Aussage: Das System soll das Erinnerungsdatum einer Rechnung bei jedem Aufruf von `SetReminderDate` aus dem aktuellen Tagesdatum zzgl. der konfigurierten Frist neu berechnen, ohne dabei selbst einen Speichervorgang auszulösen.
|
||||
Ergebnis: Der Aufrufer ist dafür verantwortlich, die Änderung zu persistieren; `SetReminderDate` selbst ändert nur das In-Memory-Objekt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs, Z. 413–427 (inkl. XML-Doc-Kommentar „Does not save the entity“) - Begründung: Durchgesetzte Methode inkl. dokumentierter Nebenwirkungsfreiheit bzgl. Persistierung.
|
||||
Prüfidee: Siehe StRS-16.
|
||||
Tracelinks: StRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-23
|
||||
Titel: Attributbasierte Autorisierung von Web-API-Endpunkten mit 401/403-Semantik
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: API-Client, ASP.NET-Middleware
|
||||
Vorbedingung: Ein Controller/eine Action ist mit `[AuthorizeUserRight(rightId)]` annotiert.
|
||||
Fakt: `UserRightAuthorizationFilter.OnAuthorization` setzt `context.Result = new UnauthorizedResult()`, wenn `context.HttpContext.User.GetCurrent()?.User == null`; setzt `context.Result = new ForbidResult()`, wenn `!currentUser.HasUserRight(_requiredRightId.Value)`.
|
||||
Aussage: Das System soll bei fehlender Authentifizierung HTTP 401 und bei vorhandener Authentifizierung ohne ausreichendes Recht HTTP 403 zurückgeben, bevor die eigentliche Controller-Aktion ausgeführt wird.
|
||||
Ergebnis: Nicht autorisierte Anfragen erreichen niemals die geschützte Aktion; der HTTP-Statuscode unterscheidet eindeutig zwischen den beiden Fehlerursachen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs, Z. 38–56 - Begründung: Durchgesetzte Filterlogik als `IAuthorizationFilter`, greift vor Controller-Ausführung.
|
||||
Prüfidee: Siehe StRS-17.
|
||||
Tracelinks: StRS-17
|
||||
Konsolidierung: Kandidat: siehe SyRS-24 (gleiche Filterinfrastruktur, unterschiedliche Verknüpfung).
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-24
|
||||
Titel: Unterstützung von Einzel-, ODER- und UND-Rechteprüfung auf API-Ebene
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: API-Client
|
||||
Vorbedingung: Ein Endpunkt ist mit `[AuthorizeAnyUserRight(...)]` oder `[AuthorizeAllUserRights(...)]` annotiert.
|
||||
Fakt: `AnyUserRightAuthorizationFilter` gewährt Zugriff, wenn mindestens eines der übergebenen Rechte vorhanden ist (`_requiredRightIds.Any(...)`); `AllUserRightsAuthorizationFilter` verlangt, dass alle übergebenen Rechte vorhanden sind (`_requiredRightIds.All(...)`); beide liefern bei leerer Rechteliste ebenfalls 403 (`_requiredRightIds.Length == 0` führt zu `ForbidResult`).
|
||||
Aussage: Das System soll neben der Einzelrechtprüfung zusätzlich ODER- und UND-verknüpfte Mehrfachrechtprüfungen auf API-Ebene unterstützen und dabei eine leere Rechteliste stets als „nicht autorisiert“ behandeln (fail-closed), nicht als „immer erlaubt“.
|
||||
Ergebnis: Ein Endpunkt mit z. B. zwei UND-verknüpften Rechten ist nur erreichbar, wenn der Benutzer beide Rechte besitzt; ein versehentlich leeres Rechte-Array sperrt den Endpunkt vollständig, statt ihn offen zu lassen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/webservice/Centron.Controllers/Authorization/AuthorizeAnyUserRightAttribute.cs, Z. 38–58 und AuthorizeAllUserRightsAttribute.cs, Z. 38–58 - Begründung: Durchgesetzte Any/All-Logik inkl. explizitem Fail-Closed-Verhalten bei leerer Liste.
|
||||
Prüfidee: Attribut mit leerem Rechte-Array `[AuthorizeAnyUserRight()]` testen und prüfen, dass der Zugriff mit 403 verweigert wird (Fail-Closed-Verhalten).
|
||||
Tracelinks: StRS-17
|
||||
Konsolidierung: Kandidat: `AuthorizeUserRightAttribute`, `AuthorizeAnyUserRightAttribute` und `AuthorizeAllUserRightsAttribute` teilen fast identischen Aufbau (nur Any/All/Single-Verknüpfung unterscheidet sich) — im Zielsystem auf einen parametrisierten Filter konsolidierbar.
|
||||
Status: belegt
|
||||
```
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
# Traceability-Tabelle — c-entron ERP
|
||||
|
||||
Konsolidierte Forward-/Backward-Traceability über StRS → SyRS → SwRS mit Primärbeleg je SwRS-Zeile. Vollständige Belegangaben (inkl. Begründung, Sekundär-/Kontextbelege) stehen in `StRS.md`, `SyRS.md`, `SwRS.md`.
|
||||
|
||||
| StRS-ID | SyRS-ID | SwRS-ID | Artefaktbeleg (Primär) |
|
||||
|---|---|---|---|
|
||||
| StRS-01 | SyRS-01 | SwRS-01 | src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs (CreateNewVersion/DoCreateNewVersion, Z. 955–1032) |
|
||||
| StRS-01 | SyRS-01 | SwRS-02 | src/backend/Centron.Entities/Entities/Sales/CustomerAssets/AssetBase.cs (State/OriginalI3D, Z. 21–27) |
|
||||
| StRS-01 | SyRS-02 | SwRS-03 | src/backend/Centron.BL/Sales/CustomerAssets/AssetBL.cs (Z. 478, objHistory.Version) |
|
||||
| StRS-02 | SyRS-03 | SwRS-04 | src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs (CancelInvoice, Z. 392–411) |
|
||||
| StRS-02 | SyRS-04 | SwRS-05 | src/shared/Centron.Controls/Converters/StateToStringConverter.cs (Z. 9–27) |
|
||||
| StRS-03 | SyRS-05 | SwRS-06 | src/backend/Centron.BL/Sales/CustomerAssets/AutomaticFactura/AutomaticFacturaBL.cs (Z. 97–129, 448–460) |
|
||||
| StRS-04 | SyRS-06 | SwRS-07 | src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs (Z. 1021–1027, 1086–1093) |
|
||||
| StRS-04 | SyRS-06 | SwRS-08 | src/backend/Centron.BL/Sales/CustomerAssets/Contracts/ContractBL.cs (Z. 324–335) |
|
||||
| StRS-05 | SyRS-07 | SwRS-09 | src/centron/Centron.WPF.UI/.../TimerBillingSettingsPageViewModel.cs (ReceiptKind-Setter, Commit baa9e7bd9b) |
|
||||
| StRS-05 | SyRS-08 | SwRS-10 | src/centron/Centron.WPF.UI/.../TimerBillingSettingsPageViewModel.cs (UpdateBillingDateIsEnabled, Z. 566–588) |
|
||||
| StRS-06 | SyRS-09 | SwRS-11 | src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (HasUserRight, Z. 644–649) |
|
||||
| StRS-06 | SyRS-09 | SwRS-12 | src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (GetAllAppRightsFromUser, Z. 651–664) |
|
||||
| StRS-06 | SyRS-10 | SwRS-13 | src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (GetRightsFromCurrentUser, Z. 63–87) |
|
||||
| StRS-07 | SyRS-11 | SwRS-14 | src/backend/Centron.BL/WebServices/CheckListArea/CentronChecklistWebserviceBL.cs (Z. 87, 160) |
|
||||
| StRS-07 | SyRS-11 | SwRS-15 | src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs (IsAdmin, Z. 56–66) |
|
||||
| StRS-08 | SyRS-12 | SwRS-16 | src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs (CheckWebRightsFromUser, Z. 113–120) |
|
||||
| StRS-08 | SyRS-12 | SwRS-17 | src/backend/Centron.BL/Administration/Rights/UserRightsExt.cs (HasWebRight, Z. 34–47) |
|
||||
| StRS-09 | SyRS-13 | SwRS-18 | src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs (GetInvoiceByFilter, Z. 435–458) |
|
||||
| StRS-09 | SyRS-13 | SwRS-19 | Grep-Fund „IsWebAccountLogin“ in OfferBL.cs/OrderBL.cs/ContractBL.cs/CreditVoucherBL.cs/DeliveryListBL.cs (SEKUNDÄR, nicht einzeln verifiziert) |
|
||||
| StRS-10 | SyRS-14 | SwRS-20 | src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs (ValidateAuthenticationPin, Z. 43–54) |
|
||||
| StRS-10 | SyRS-14 | SwRS-21 | src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs (Named Queries PasswordManager, Z. 29–41, 56–74) |
|
||||
| StRS-11 | SyRS-15 | SwRS-22 | src/backend/Centron.BL/Security/PdfSigningBL.cs (GetPdfSigningSettings, Z. 29–55) |
|
||||
| StRS-11 | SyRS-16 | SwRS-23 | src/backend/Centron.BL/Security/PdfSigningBL.cs (SavePdfSigningSettings Rechteprüfung, Z. 57–64) |
|
||||
| StRS-11, StRS-18 | SyRS-17 | SwRS-24 | src/backend/Centron.BL/Security/PdfSigningBL.cs (EncryptText-Aufrufe, Z. 77–100) |
|
||||
| StRS-12 | SyRS-18 | SwRS-25 | src/backend/Centron.Entities/Entities/CustomerArea/Support/HelpdeskState.cs (Z. 1–16) |
|
||||
| StRS-13 | SyRS-19 | SwRS-26 | src/backend/Centron.Interfaces/Sales/Helpdesks/ShowHelpdeskRight.cs (Z. 1–10) |
|
||||
| StRS-14 | SyRS-20 | SwRS-27 | src/backend/Centron.BL/Warehousing/ArticleBL.cs (Z. 2783) |
|
||||
| StRS-15 | SyRS-21 | SwRS-28 | src/backend/Centron.BL/Sales/CustomerAssets/CustomerAssetBL.cs (GetNewAsset, Z. 126–150) |
|
||||
| StRS-16 | SyRS-22 | SwRS-29 | src/backend/Centron.BL/Sales/CustomerAssets/Invoices/InvoiceBL.cs (SetReminderDate, Z. 413–427) |
|
||||
| StRS-17 | SyRS-23 | SwRS-30 | src/webservice/Centron.Controllers/Authorization/AuthorizeUserRightAttribute.cs (Z. 38–56) |
|
||||
| StRS-17 | SyRS-24 | SwRS-31 | src/webservice/Centron.Controllers/Authorization/AuthorizeAnyUserRightAttribute.cs, AuthorizeAllUserRightsAttribute.cs (Z. 33–58) |
|
||||
| StRS-18 | SyRS-17 | SwRS-24 | (siehe oben — StRS-18 referenziert dieselbe SyRS/SwRS-Kette wie StRS-11 bzgl. Verschlüsselung) |
|
||||
|
||||
## Hinweise zur Tabelle
|
||||
|
||||
- Jede Zeile ist eindeutig durch die Kombination StRS/SyRS/SwRS identifizierbar; Mehrfachverwendung derselben SwRS-ID (z. B. SwRS-24) ist beabsichtigt, da eine technische Maßnahme (AES-Verschlüsselung) zwei Stakeholder-Anforderungen gleichzeitig erfüllt (Signaturfunktion StRS-11 und generelle Verschlüsselungsanforderung StRS-18).
|
||||
- Zeilen mit ausschließlich SEKUNDÄR-Beleg (z. B. StRS-09/SwRS-19) sind entsprechend gekennzeichnet und in `Hypothesen.md` referenziert, sofern eine offene Verifikationsfrage besteht.
|
||||
- Ein maschineller Konsistenzcheck (Duplikate, verwaiste IDs, tote Tracelinks) wurde durchgeführt; Ergebnis siehe `Analysebericht.md`, Abschnitt „Konsistenzcheck“.
|
||||
+213
@@ -0,0 +1,213 @@
|
||||
# Messprotokoll – V1 (Baseline, solo) – Prompt-Version 01, Lauf 10 (Lauf D)
|
||||
|
||||
> V1-Messung im Agentenmodus `solo`. Teil eines Dreier-Parallelblocks (Läufe C, D, E), der die
|
||||
> V1-Reihe von zwei auf fünf Messpunkte bringt.
|
||||
>
|
||||
> **Parallelbetrieb:** Dieser Lauf lief zeitgleich mit `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180416_v3.3.0-5851`
|
||||
> und `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180418_v3.3.0-b676`. Drei Läufe konkurrierten um CPU, Netzwerk und
|
||||
> API-Kontingent. **Wanduhrzeit, `duration_ms` und `duration_api_ms` sind dadurch verzerrt**
|
||||
> und nicht mit seriellen Läufen vergleichbar. Tokens, Kosten, 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-25T18:04:43.9408007+02:00
|
||||
- **Endzeit:** 2026-08-25T18:22:32.2314071+02:00
|
||||
- **Dauer gesamt:** 00:17:49 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:17:47 (`duration_ms`) — API: 00:16:39
|
||||
- **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.3.0-664e`
|
||||
- **Ablage:** `Iteration 1/claude-sonnet-5/solo/high/`
|
||||
- **Parallele Läufe:** ja – `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180416_v3.3.0-5851`, `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180418_v3.3.0-b676`
|
||||
- **Skill-Version:** `3.3.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` — **nicht zur Laufzeit gesetzt**, sondern aus der Sitzung geerbt und
|
||||
nachträglich aus dem Session-Transkript rekonstruiert (117 Nachrichten, durchgängig `high`).
|
||||
`RawResult.json` enthält kein `effort`-Feld. Ab Skill-Version 3.4.0 wird der Wert per
|
||||
`--effort` explizit gesetzt.
|
||||
- **Modell:** `claude-sonnet-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
|
||||
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 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)
|
||||
- **Fast-Mode:** aus
|
||||
|
||||
## Verbrauch
|
||||
|
||||
### Hauptagent (`usage`)
|
||||
| Messgröße | Wert |
|
||||
|---|---|
|
||||
| Input-Tokens | 92 |
|
||||
| Output-Tokens | 103.789 (davon 22.957 Thinking-Tokens) |
|
||||
| Cache-Write-Tokens | 157.686 |
|
||||
| Cache-Read-Tokens | 4.325.949 |
|
||||
| Agent-Turns | 77 |
|
||||
|
||||
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
|
||||
| Messgröße | `claude-sonnet-5` | `claude-haiku-4-5-20251001` | Summe |
|
||||
|---|---:|---:|---:|
|
||||
| Input-Tokens | 92 | 4.192 | 4.284 |
|
||||
| Output-Tokens | 103.789 | 25 | 103.814 |
|
||||
| Cache-Write-Tokens | 157.686 | 0 | 157.686 |
|
||||
| Cache-Read-Tokens | 4.325.949 | 0 | 4.325.949 |
|
||||
| Tokens gesamt | 4.587.516 | 4.217 | **4.591.733** |
|
||||
|
||||
**Tokens gesamt: 4.591.733** (Summe aus Input, Output, Cache-Write und Cache-Read ueber alle Modelle; `total_cost_usd` steht weiterhin in `RawResult.json`)
|
||||
|
||||
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-sonnet-5` identisch.
|
||||
|
||||
## Ergebnis
|
||||
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
|
||||
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
|
||||
- **Session-ID:** `e9b18633-b841-4748-b945-642d48e23c23`
|
||||
- **Permission-Denials:** **0** – auch keine auf `Task`/`Agent`/`Workflow`
|
||||
- **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` | 30.712 B | 18 Anforderungen |
|
||||
| `SyRS.md` | 32.884 B | 24 Anforderungen |
|
||||
| `SwRS.md` | 36.354 B | 31 Anforderungen |
|
||||
| `Traceability.md` | 5.282 B | 33 Datenzeilen |
|
||||
| `Hypothesen.md` | 6.244 B | Sammlung der `[HYPOTHESE]`-Aussagen |
|
||||
| `Glossar.md` | 5.995 B | Domänenbegriffe |
|
||||
| `Analysebericht.md` | 11.639 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
|
||||
|
||||
Summe: **73 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`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 18 | 24,7 % |
|
||||
| SyRS | 24 | 32,9 % |
|
||||
| SwRS | 31 | 42,5 % |
|
||||
| **Gesamt** | **73** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 29 | 39,7 % |
|
||||
| Sicherheit | 28 | 38,4 % |
|
||||
| Daten | 13 | 17,8 % |
|
||||
| nicht-funktional (Sicherheit/Konfigurierbarkeit) | 2 | 2,7 % |
|
||||
| nicht-funktional (Performanz-Effizienz) | 1 | 1,4 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 91 |
|
||||
| davon `PRIMÄR` | 77 (84,6 %) |
|
||||
| davon `SEKUNDÄR` | 7 (7,7 %) |
|
||||
| davon `KONTEXT` | 7 (7,7 %) |
|
||||
| Belege je Anforderung (Median) | 1 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (97,3 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 65 | 89,0 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 8 | 11,0 % |
|
||||
| als Workaround vermerkt | 4 | 5,5 % |
|
||||
| Konsolidierungskandidaten | 9 | 12,3 % |
|
||||
| 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** (40 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 73 von 73 mit Tracelinks (100,0 %) |
|
||||
|
||||
## V1-Reihe: fünf Messpunkte unter identischer Bedingung
|
||||
|
||||
| | Lauf A | Lauf B | **Lauf C** | **Lauf D** | **Lauf E** |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| Anforderungen | 42 | 82 | **60** | **73** | **67** |
|
||||
| — StRS/SyRS/SwRS | 14/15/13 | 20/34/28 | **17/19/24** | **18/24/31** | **19/20/28** |
|
||||
| Tokens gesamt | 4.357.855 | 12.598.503 | **5.659.692** | **4.591.733** | **5.050.595** |
|
||||
| Output-Tokens | 70.749 | 129.077 | **95.147** | **103.814** | **89.793** |
|
||||
| Thinking-Tokens | 10.470 | 21.863 | **14.407** | **22.957** | **11.962** |
|
||||
| Cache-Read | 4,12 M | 12,23 M | **5,35 M** | **4,33 M** | **4,73 M** |
|
||||
| Agent-Turns | 68 | 107 | **72** | **77** | **67** |
|
||||
| Traceability-Zeilen | 19 | 36 | **39** | **33** | **31** |
|
||||
| Denials / Subagenten | 0 / 0 | 0 / 0 | **0 / 0** | **0 / 0** | **0 / 0** |
|
||||
|
||||
**V1 gesamt:** Anforderungen 42–82 (Median 67), Tokens 4.357.855–12.598.503 (Median 5.050.595).
|
||||
|
||||
## Vergleich V1 (solo) gegen V1b (builtin)
|
||||
|
||||
| | V1 (5 Läufe) | V1b (4 vollständige Läufe) |
|
||||
|---|---|---|
|
||||
| Anforderungen | 42 – 82 (Faktor **2,0**) | 55 – 325 (Faktor **5,9**) |
|
||||
| Tokens gesamt | 4.357.855 – 12.598.503 (Faktor **2,9**) | 11.516.200 – 52.713.542 (Faktor **4,6**) |
|
||||
| Median Tokens | **5.050.595** | **30.065.183** |
|
||||
| Subagenten | 0 (erzwungen) | 0 – 14 (selbstgewählt) |
|
||||
|
||||
## Anmerkungen/Auffälligkeiten
|
||||
|
||||
1. **V1 ist deutlich stabiler als V1b.** Die drei parallelen Läufe C, D und E liegen bei 60, 73
|
||||
und 67 Anforderungen und 2,86, 2,54 und 5.050.595 Tokens – eine Spanne von nur ±11 % bzw. ±6 %.
|
||||
Über alle fünf V1-Läufe beträgt die Streuung Faktor 2,0 (Anforderungen) und 2,9 (Tokens),
|
||||
gegenüber Faktor 5,9 und 4,6 in V1b. **Die selbstgewählte Zerlegung in Subagenten ist damit
|
||||
als Hauptursache der V1b-Streuung bestätigt:** Wird sie unterbunden, schrumpft die Streuung
|
||||
auf weniger als die Hälfte.
|
||||
|
||||
2. **V1 kostet ein Vielfaches weniger.** Median 5.050.595 Tokens gegenüber 30.065.183 in V1b, und
|
||||
selbst der teuerste V1-Lauf (12.598.503 Tokens) liegt unter dem günstigsten V1b-Lauf (11.516.200 Tokens).
|
||||
Ursache sind die deutlich niedrigeren Cache-Read-Tokens: 4,1 bis 12,2 Mio. gegenüber 10,5 bis
|
||||
44,8 Mio. Ohne parallele Kontexte entfällt das mehrfache Einlesen derselben Artefakte.
|
||||
|
||||
3. **Lauf B bleibt der Ausreißer der V1-Reihe.** Mit 82 Anforderungen, 12.598.503 Tokens und 12,23 Mio.
|
||||
Cache-Reads liegt er deutlich über den vier übrigen V1-Läufen, die eng zwischen 42 und 73
|
||||
bzw. 2,20 und 5.659.692 Tokens liegen. Bei fünf Messpunkten ist das noch nicht als Ausreißer im
|
||||
statistischen Sinn zu behandeln, aber als Beobachtung festzuhalten.
|
||||
|
||||
4. **Effort war durchgängig `high`** – für alle drei Läufe aus den Transkripten belegt
|
||||
(95 bis 117 Nachrichten je Lauf). Der Denkaufwand scheidet damit als Erklärung für
|
||||
verbleibende Unterschiede innerhalb der V1-Reihe aus.
|
||||
|
||||
5. **Dreifachparallelität technisch fehlerfrei.** Alle drei Läufe schrieben in getrennte
|
||||
Verzeichnisse mit eigenem `_meta`. Keine Kollision, keine gegenseitige Überschreibung, alle
|
||||
drei Ergebnisverzeichnisse frei von Fremddateien, Root unverändert. Das Verfahren aus
|
||||
Skill-Version 3.1.0 skaliert auch über zwei gleichzeitige Läufe hinaus.
|
||||
|
||||
6. **Wanduhrzeiten nicht auswerten.** Alle drei Läufe brauchten 16:29 bis 17:49 – bei drei
|
||||
konkurrierenden Prozessen auf einer Maschine ist das kein inhaltliches Signal. Für
|
||||
Laufzeitvergleiche seriell messen.
|
||||
|
||||
7. **Manuelle Eingriffe während des Laufs:** keine.
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"is_error":false,"duration_api_ms":999443,"num_turns":77,"stop_reason":"end_turn","session_id":"e9b18633-b841-4748-b945-642d48e23c23","total_cost_usd":2.5383248000000003,"usage":{"input_tokens":92,"cache_creation_input_tokens":157686,"cache_read_input_tokens":4325949,"output_tokens":103789,"output_tokens_details":{"thinking_tokens":22957},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":157686,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":646,"cache_read_input_tokens":184749,"cache_creation_input_tokens":660,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":660},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":25,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.0043170000000000005,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-sonnet-5":{"inputTokens":92,"outputTokens":103789,"cacheReadInputTokens":4325949,"cacheCreationInputTokens":157686,"webSearchRequests":0,"costUSD":2.5340078000000004,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-sonnet-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":"All seven output files are in place. No source files in the analyzed codebase were modified.\n\n## Summary\n\nI produced a consolidated StRS/SyRS/SwRS specification (18/24/31 requirements) for the c-entron ERP codebase, following the RRE method chain (steps 2–6) as prompted. Given the codebase's real scale (~15,500 C# files across ~85 business-logic modules), full exhaustive coverage wasn't feasible in one pass, so I deliberately deep-dived a representative cross-section with strong evidence quality:\n\n- **Document lifecycle**: asset versioning, invoice cancellation/storno\n- **Billing**: automatic collective invoicing, contract-based recurring billing, TimerBilling\n- **Security/rights**: group-based permission model (Sichtrus/Sichmemb), admin bypass, web-portal rights isolation, 2FA, API authorization attributes\n- **Other**: PDF digital signing + encryption at rest, ticket status/visibility scoping, article stock tracking, customer finance-condition inheritance\n\nEvery requirement carries a file/line-level artifact reference classified PRIMÄR/SEKUNDÄR/KONTEXT, with security- and billing-relevant ones backed by at least one PRIMÄR (enforced code) reference as required. Seven open `[HYPOTHESE]` items and the full coverage/gap map (what was deeply read vs. sampled vs. untouched) are documented in `Hypothesen.md` and `Analysebericht.md`. A consistency check found and fixed one broken tracelink (StRS-01 → SyRS-02); no duplicate IDs or unsupported requirements remain.\n\nAll files are at `Ergebnisse\\` in the run directory: `StRS.md`, `SyRS.md`, `SwRS.md`, `Traceability.md`, `Hypothesen.md`, `Glossar.md`, `Analysebericht.md`.","ttft_ms":3383,"ttft_stream_ms":1090,"time_to_request_ms":40,"type":"result","duration_ms":1066536,"uuid":"1dfc8f52-16f5-4b61-9f65-392442f11d90","queued_turn_count":0}
|
||||
+1261
File diff suppressed because it is too large
Load Diff
+60
@@ -0,0 +1,60 @@
|
||||
## Gefundene Anforderungen
|
||||
|
||||
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 18 | 24,7 % |
|
||||
| SyRS | 24 | 32,9 % |
|
||||
| SwRS | 31 | 42,5 % |
|
||||
| **Gesamt** | **73** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 29 | 39,7 % |
|
||||
| Sicherheit | 28 | 38,4 % |
|
||||
| Daten | 13 | 17,8 % |
|
||||
| nicht-funktional (Sicherheit/Konfigurierbarkeit) | 2 | 2,7 % |
|
||||
| nicht-funktional (Performanz-Effizienz) | 1 | 1,4 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 91 |
|
||||
| davon `PRIMÄR` | 77 (84,6 %) |
|
||||
| davon `SEKUNDÄR` | 7 (7,7 %) |
|
||||
| davon `KONTEXT` | 7 (7,7 %) |
|
||||
| Belege je Anforderung (Median) | 1 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 71 (97,3 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 65 | 89,0 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 8 | 11,0 % |
|
||||
| als Workaround vermerkt | 4 | 5,5 % |
|
||||
| Konsolidierungskandidaten | 9 | 12,3 % |
|
||||
| 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** (40 risikorelevante Anforderungen, alle gedeckt) |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 73 von 73 mit Tracelinks (100,0 %) |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+132
@@ -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_180417_sonnet5_solo_v3.3.0-664e\Ergebnisse\`.
|
||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:22:32.2314071+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:04:43.9408007+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# Subagenten-Aufrufe
|
||||
|
||||
Session `e9b18633-b841-4748-b945-642d48e23c23`, Transkript `e9b18633-b841-4748-b945-642d48e23c23.jsonl`.
|
||||
|
||||
`subagent_stats`: **0** Subagenten gesamt, davon **0** von Subagenten gestartet (max_depth 0). Direkt vom Hauptagenten erwartet: **0**. Im Transkript gefunden: **0**.
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
# Analysebericht — RRE c-entron ERP, V1 Baseline, Iteration 01
|
||||
|
||||
## 1. Rahmenbedingungen dieser Iteration
|
||||
|
||||
- **Scope (Vorgabe):** gesamte Codebasis, keine Modulbeschränkung, aber selbstständige Priorisierung der Analysetiefe (siehe Auftrag, Schritt 1).
|
||||
- **Werkzeuge:** ausschließlich Datei-basiertes Lesen (Read/Grep/Glob/Bash) auf dem lokalen Arbeitsverzeichnis; keine Ausführung, keine spezialisierten Agenten, kein MCP.
|
||||
- **Größenordnung der Codebasis:** 16.063 C#-Dateien, 1.233 XAML-Dateien, Lösung `Centron.sln` mit >30 Projekten, gegliedert in `src/backend` (Domänenlogik/Datenzugriff), `src/centron` (WPF-Client), `src/webservice` (REST-API-Host), `src/apis` (Distributoren-/Zahlungs-Integrationen), `src/nexus` (Outlook-Add-in-Backend), `src/shared` (Cross-Cutting UI-Controls/Core).
|
||||
- **Zeitliche/Umfangsbedingte Realität:** Eine vollständige Tiefenanalyse aller ~90 Business-Logic-Unterordner (`src/backend/Centron.BL/*`) mit insgesamt >1.500 Dateien allein in diesem Projekt ist im Rahmen einer einzelnen Iteration nicht mit belastbarer Beleglage (PRIMÄR-Code-Nachweis statt Vermutung) leistbar. Es wurde daher bewusst in die Tiefe statt in die Breite priorisiert (siehe Abschnitt 2).
|
||||
|
||||
## 2. Abdeckung — was wurde wie tief analysiert
|
||||
|
||||
### 2.1 Vollständig/tief analysiert (Code direkt gelesen, PRIMÄR-Belege erhoben)
|
||||
|
||||
| Bereich | Repräsentative Dateien/Klassen | Requirements |
|
||||
|---|---|---|
|
||||
| Belegwesen-Kern (Sales/Receipts) | `ReceiptBase.cs`, `ReceiptState.cs`, `ReceiptInvoice.cs`, `ReceiptBL.cs` (Kreditlimit- und Statuslogik, gezielte Zeilenbereiche einer >10.000-Zeilen-Klasse) | StRS-01/02/07, SyRS-01/02/07, SwRS-01/03/04/13 |
|
||||
| Rechte-/Sicherheitsmodell | `AppRightsBL.cs`, `TwoFactorAuthenticationBL.cs`, `PasswordManagerBL.cs` (Auszug), `DeveloperSecurity.cs`, `LicenseManager.cs` (Auszug) | StRS-09/10/11/16, SyRS-09/10/11/12/17, SwRS-16/17/18/19/20/27 |
|
||||
| Lager/Artikel (Warehousing) | `Article.cs` (Auszug), `ArticleBL.cs` (Rechteprüfungsblock) | StRS-14, SyRS-15, SwRS-24 |
|
||||
| Kunden-/Kontoentität | `Customer.cs`, `AccountCustomer.cs`, `AccountBL.cs` (Auszug) | StRS-07/08, SyRS-07/08, SwRS-14/15 |
|
||||
|
||||
### 2.2 Mittel analysiert (ausführliche, entwicklerseitig gepflegte Architektur-Dokumentation gelesen und als SEKUNDÄR/KONTEXT-Beleg herangezogen, Code nur punktuell/exemplarisch verifiziert)
|
||||
|
||||
| Bereich | Quelle | Requirements |
|
||||
|---|---|---|
|
||||
| Belegversionierung | `docs/reference/receipts/receipts-backend-architecture.md` | StRS-03, SyRS-03, SwRS-02/05/06 |
|
||||
| Belegsuche | `docs/reference/receipts/receipt-search-architecture.md` | StRS-04/18, SyRS-04/19, SwRS-07/08 |
|
||||
| Vertrag/Abrechnung/RMM | `docs/reference/receipts/contracts-backend.md`, `Contract-Billing-RMM-Article-Logic.md` | StRS-05/06, SyRS-05/06, SwRS-09/10/11/12 |
|
||||
| Aktionspreise | `docs/reference/receipts/actionprice-system.md` | StRS-13, SyRS-14, SwRS-23 |
|
||||
| EDI-Lieferantenintegration | `docs/reference/edi/edi-architecture.md` | StRS-12, SyRS-13, SwRS-21/22 |
|
||||
| E-Rechnung (ZUGFeRD/XRechnung) | `docs/reference/zugferd-field-mapping.md` | StRS-15, SyRS-16, SwRS-25/26 |
|
||||
| Lizenzsystem (Konzept) | `docs/reference/security/licensing-system.md` | StRS-11, SyRS-12 |
|
||||
| Architekturmuster (Result/Response, DTO/Entity, ILogic-Dualarchitektur) | `docs/reference/architecture/*.md`, `docs/getting-started/general-structure.md` | StRS-17/19, SyRS-18/20, SwRS-28 |
|
||||
|
||||
**Einordnung dieser Dokumentation:** Es handelt sich um im Repository geführte, offensichtlich entwicklerseitig gepflegte technische Referenzdokumentation (`docs/reference/*`, `docs/guides/*`) mit hoher Detailtiefe und häufig direkten Codezitaten/Zeilenverweisen. Sie wurde durchgehend als **SEKUNDÄR** oder **KONTEXT** (nicht PRIMÄR) klassifiziert, da sie selbst kein durchgesetzter Code ist — auch wenn ihr Detailgrad in mehreren Fällen über eine reine Beschreibung hinausgeht und wörtliche Codeauszüge enthält. Wo möglich, wurde zusätzlich die zitierte Originaldatei direkt gelesen, um einen PRIMÄR-Beleg zu erhalten (z. B. `ReceiptState.cs`, `AppRightsBL.cs`, `DeveloperSecurity.cs`).
|
||||
|
||||
### 2.3 Nur oberflächlich erfasst (Verzeichnisstruktur/Dateizahl erhoben, keine inhaltliche Analyse)
|
||||
|
||||
Die folgende Tabelle zeigt die Größe (Anzahl `.cs`-Dateien) aller Unterordner von `src/backend/Centron.BL/`, um die Größenordnung der nicht vertieft analysierten Bereiche transparent zu machen:
|
||||
|
||||
| Ordner | Dateien | Analysetiefe in dieser Iteration |
|
||||
|---|---|---|
|
||||
| Administration | 959 | keine (nur Unterordnerliste: Rights, Licensing, Scripts, Settings, Employees, Mandatory, Company, Themes, WebServiceConfiguration, DataSecurity, ... — punktuell nur `Rights/AppRightsBL.cs` und `Licensing/LicenseManager.cs` gelesen) |
|
||||
| WebServices | 464 | keine eigenständige (i. d. R. reine DTO-Konvertierungsschicht zu den o. g. BL-Klassen, nicht separat untersucht) |
|
||||
| Sales | 248 | teilweise (`Receipts/ReceiptBL.cs` punktuell; `Customers`, `CustomerAssets`, `Marketing`, `Support`, `CashBooks`, `HourlySurchargeRatesBL`, `Calendar`, `DocumentationWizardArea` nicht gelesen) |
|
||||
| Warehousing | 40 | teilweise (`ArticleBL.cs` punktuell; `ArticleUnitBL`, `ArticleVariableBL`, `ArticleVolumePricesBL`, `BarcodeBL`, `CostCenterBL`, `CostObjectBL`, `TaxBL`, `SecondStockArticleBL` nicht gelesen) |
|
||||
| Accounts | 29 | keine (nur `AccountBL.cs` punktuell über Grep-Treffer) |
|
||||
| EDI | 27 | keine (nur über Dokumentation erschlossen, kein `.cs` gelesen) |
|
||||
| ReportEngine | 26 | keine |
|
||||
| ArtificialIntelligence | 25 | keine |
|
||||
| DataExchange | 23 | keine |
|
||||
| Mail | 20 | keine |
|
||||
| Statistics | 16 | keine |
|
||||
| Services | 11 | keine |
|
||||
| Finances, EmployeeArea | je 9 | keine |
|
||||
| MyDay, IndexSearch, CustomerArea | je 7 | keine |
|
||||
| PasswordManagementArea, Helpers, GUI | je 5-6 | keine (PasswordManager selbst separat unter `BL/PasswordManager/` mit 1 Datei geprüft) |
|
||||
| **Alle übrigen ~65 Ordner** (WebSuite, TaskManager, RiverDivo, Purchasing, MyCentron, SocialMedia, Modules, DocuBoard, CheckListArea, Urls, TradePool, ToDoArea, TextModuleArea, Storage, SelfCare, Resources, Production, Notifications, Mailings, Logistics, Integrations, CountryArea, CentronIcons, CPra, BusinessPartner, WebVersion, VoucherManagement, VideoPortal, Transactions, Tools, Time, TicketProjects, Telemetry, Tapi, Tags, SystemArea, Start, Reporting, Projects, ProductMatrix, Processes, Outlook, ObjectExternalReferences, NexusTicketViews, Mobile, MassUpdate, MailScanner, ItPlanner, Gateway, ExternalToolsBL, ExternalHelpdesk, ExpectedEvents, Exceptions, DocumentationArea, Devices, Customizations, Chats, ChangeTracking, CentronNexus, Calendar, Buying, AppointmentRequests, Accounting) | je 1-4 | **keine** — nur Verzeichnisname registriert |
|
||||
|
||||
Zusätzlich vollständig unanalysiert: `src/centron/Centron.WPF.UI` (WPF-Client, 1.233 XAML-Dateien und zugehörige Code-Behind/ViewModels), `src/apis/*` (externe API-Integrationen GLS, Shipcloud, FinAPI, ITscope, Icecat, Egis, COP), `src/nexus/*` (Outlook-Add-in), `docker/*`, `deployment/*`, `azure/*` (CI/CD- und Deployment-Konfiguration), sämtliche `tests/*`-Projekte (die als Verifikationsquelle für bestehende Anforderungen wertvoll gewesen wären, aber nicht ausgewertet wurden), sowie jegliche SQL-Skripte/Datenbankschemata außerhalb der in Entwicklerdokumentation zitierten Tabellenausschnitte.
|
||||
|
||||
### 2.4 Nicht erhobene Artefaktklassen
|
||||
|
||||
- **Ticket-/Issue-Tracker-Daten** (z. B. Jira/Azure-Boards-Exporte): nicht im Arbeitsverzeichnis als Datei vorhanden, daher nicht erhoben (Commit-Messages verweisen auf Ticketnummern, z. B. "Ticket 168496", die aber nicht auflösbar waren).
|
||||
- **Release Notes** außerhalb von Commit-Messages: keine dedizierte Release-Notes-Datei gefunden.
|
||||
- **Migrationsnotizen**: nicht als eigenständige Artefakte identifiziert; Migrationshinweise sind implizit in `docs/reference/*`-Dokumenten enthalten (z. B. Versionstabellen-Wartungshinweise).
|
||||
- **Datenbankschemata als eigenständige `.sql`-Dateien**: Suche nach `*.sql` im Arbeitsverzeichnis ergab 0 Treffer; Schema-Informationen stammen ausschließlich aus Entwicklerdokumentation und C#-Mapping-Klassen (nicht direkt gelesen, nur referenziert).
|
||||
- **Commit-Historie**: `git log` wurde oberflächlich gesichtet (letzte 20 Commits), aber nicht systematisch als Anforderungsquelle ausgewertet (z. B. keine Analyse von Bugfix-Commits als Hinweis auf implizite Geschäftsregeln).
|
||||
|
||||
## 3. Konsistenzcheck über das gesamte Anforderungs-Set
|
||||
|
||||
- **Doppelte/mehrfach vergebene IDs:** Keine gefunden. StRS-01..19, SyRS-01..20, SwRS-01..28 sind jeweils genau einmal vergeben (manuell durchgezählt beim Erstellen von Traceability.md).
|
||||
- **Anforderungen ohne Beleg:** Keine gefunden — jede der 67 Anforderungen (19+20+28) führt mindestens einen klassifizierten Beleg. Risikoanforderungen (Sicherheit, Rechte, Abrechnung/Kreditlimit) führen mit einer Ausnahme mindestens einen PRIMÄR-Beleg:
|
||||
- **Ausnahme:** StRS-08/SyRS-08/SwRS-15 (Mahnstufensperre) besitzt keinen PRIMÄR-Beleg für die eigentliche Durchsetzung und ist daher korrekt als `[HYPOTHESE]` markiert (siehe Hypothesen.md).
|
||||
- **Tracelinks auf nicht existierende IDs:** Keine gefunden. Alle Tracelinks in StRS/SyRS/SwRS wurden gegen die tatsächlich vergebenen IDs in Traceability.md abgeglichen.
|
||||
- **Nicht vollständig verfeinerte SyRS:** SyRS-19 und SyRS-20 haben keine 1:1-eigene SwRS-Konkretisierung (siehe Traceability.md, Abschnitt "Nicht abgedeckte Verknüpfungen") — dies ist dokumentiert und beabsichtigt, keine Inkonsistenz.
|
||||
|
||||
## 4. Konsolidierungshinweise
|
||||
|
||||
Im untersuchten Ausschnitt wurde **keine** eindeutig redundante Mehrfachimplementierung derselben fachlichen Funktion auf Anforderungsebene identifiziert (Feld `Konsolidierung` ist bei allen 67 Anforderungen `nein`, mit einer Ausnahme). Das ist eine Folge des engen Scopes dieser Iteration (wenige, tief analysierte Bereiche) und **kein Beleg dafür, dass die Codebasis frei von Redundanz ist** — im Gegenteil deutet allein die Größe von `Administration` (959 Dateien) und die in `docs/getting-started/general-structure.md` explizit eingeräumte Aussage ("there are tons of places where this general structure does not apply... horrific code") auf erhebliches Konsolidierungspotenzial hin, das mit dem aktuellen Scope nicht sichtbar gemacht werden konnte.
|
||||
|
||||
- **Einziger dokumentierter Konsolidierungs-Kandidat:** SwRS-06 ↔ SwRS-05 (Versionierungsschema und Kopiervorgang könnten in einer gemeinsamen Testspezifikation zusammengeführt werden).
|
||||
|
||||
## 5. Selbstbewertung
|
||||
|
||||
### 5.1 Vollständig analysiert
|
||||
Kein Modul wurde im Sinne einer vollständigen Zeile-für-Zeile-Analyse abgedeckt — selbst die "tief" analysierten Bereiche (Abschnitt 2.1) beruhen auf gezielten Ausschnitten sehr großer Klassen (z. B. `ReceiptBL.cs` mit laut Dokumentation "über 10.000 Zeilen Code", von denen nur ca. 300 Zeilen gezielt gelesen wurden).
|
||||
|
||||
### 5.2 Stichprobenhaft/mittel analysiert
|
||||
Belegwesen (Sales/Receipts inkl. Verträge), Sicherheits-/Rechtemodell, Lizenzierung, EDI, Aktionspreise, E-Rechnung, Lager-Rechtesystem — jeweils über eine Kombination aus gezieltem Quellcode-Lesen und hochwertiger, im Repository geführter Architekturdokumentation.
|
||||
|
||||
### 5.3 Gar nicht analysiert
|
||||
- Der komplette WPF-UI-Client (`Centron.WPF.UI`, 1.233 XAML-Dateien) — UI-Validierungslogik, ViewModel-Geschäftsregeln und Menü-/Rechtefreischaltung auf UI-Ebene sind nicht erfasst.
|
||||
- Administration (959 Dateien) bis auf Rights/Licensing — u. a. Benutzerverwaltung, Mandanteneinstellungen, Datenschutz/DataSecurity, Skript-Migrationssystem, Themes, Netzwerkdiagnose.
|
||||
- Alle externen API-Integrationen (`src/apis/*`) — GLS, Shipcloud, FinAPI, ITscope, Icecat, Egis, COP.
|
||||
- Finances/Accounting (Buchhaltungsexport, Kostenrechnung) über die in ZUGFeRD-Dokumentation gestreiften Aspekte hinaus.
|
||||
- Projektmanagement/Ticketing (TicketProjects, Projects, ItPlanner, CheckListArea, ToDoArea, TaskManager).
|
||||
- Kommunikation/Kollaboration (Mail, Mailings, Chats, MailScanner, Nexus/Outlook-Integration, VideoPortal, SocialMedia).
|
||||
- Reporting/Statistik (ReportEngine, Reporting, Statistics, IndexSearch).
|
||||
- Mobile, WebSuite, SelfCare, MyDay, MyCentron (Endkunden-/Mitarbeiter-Self-Service-Portale).
|
||||
- Künstliche Intelligenz (`ArtificialIntelligence`-Ordner in BL und Administration) — trotz Namens nicht untersucht; angesichts der Laufzeitvorgabe "keine KI-Assistenz-Konfigurationen" (siehe letzter Commit) ggf. für Folgeiterationen relevant zu klären, was dieser Ordner tatsächlich enthält.
|
||||
- Sämtliche Testprojekte (`tests/*`) — hätten als Verifikationsquelle für die hier aufgestellten Prüfideen dienen können, wurden aber nicht ausgewertet.
|
||||
- Datenbankschemata/SQL-Skripte als eigenständige Artefakte.
|
||||
- Deployment/CI-CD (`deployment/*`, `azure/*`, `docker/*`) — relevant für Betriebs-/Sicherheitsanforderungen (SyRS-Kategorie "Konfigurationen, Deployment-Skripte, Logging-Policies"), in dieser Iteration nicht erhoben trotz expliziter Aufforderung im Auftrag, solche Artefakte gezielt heranzuziehen. **Dies ist die größte bewusst offene Lücke dieser Iteration.**
|
||||
|
||||
### 5.4 Stellen mit dünner Beleglage
|
||||
- **SwRS-02** (duale Tabellen-/View-Architektur): beruht vollständig auf SEKUNDÄR-Dokumentation ohne eigene Verifikation im `SaveReceipt*Repository`-Code selbst.
|
||||
- **StRS-08/SyRS-08/SwRS-15** (Mahnstufensperre): als `[HYPOTHESE]` markiert, dünnste Beleglage des gesamten Sets.
|
||||
- **StRS-19/SyRS-20** (Lokalisierung): rein auf Richtliniendokumentation gestützt, keine Stichprobenprüfung der tatsächlichen `.resx`-Vollständigkeit durchgeführt.
|
||||
- **SwRS-18** (Konsistenz der Lizenzprüfung über alle `PasswordManagerBL`-Methoden): nur eine von vermutlich vielen Methoden wurde gelesen; die Aussage "alle Methoden prüfen konsistent" ist eine Extrapolation aus einem einzigen Beispiel und sollte in einer Folgeiteration an weiteren Methoden verifiziert werden.
|
||||
|
||||
### 5.5 Empfehlungen für eine Folgeiteration
|
||||
|
||||
1. **Administration (959 Dateien) gezielt aufschlüsseln**, insbesondere `DataSecurity`, `Employees`, `Mandatory`, `Scripts` (Migrationsmechanismus selbst) und `WebServiceConfiguration` — hier ist die größte unentdeckte Fläche der Codebasis.
|
||||
2. **Deployment-/Betriebsartefakte (`deployment/*`, `azure/*`, `docker/*`) auswerten**, da der Auftrag explizit Betriebs- und Sicherheitsanforderungen aus solchen Artefakten fordert und dies in dieser Iteration nicht geschehen ist.
|
||||
3. **Datenbankschemata direkt verifizieren** (z. B. über Mapping-Klassen in `Centron.DAO/Mappings/*` oder — falls zugänglich — Schema-Dumps), um die aktuell nur dokumentationsbasierten SwRS-Aussagen zur Versionstabellen-Struktur (SwRS-05/06) auf PRIMÄR-Niveau zu heben.
|
||||
4. **Hypothese H-01 (Mahnstufensperre) auflösen** durch gezielte Volltextsuche außerhalb der bisher durchsuchten Verzeichnisse (insbesondere WPF-UI-ViewModels) sowie Fachbereichs-Rückfrage.
|
||||
5. **Test-Suiten (`tests/*`) als Anforderungsquelle heranziehen** — Testfälle enthalten häufig implizit dokumentierte Geschäftsregeln und könnten bestehende SEKUNDÄR-Belege auf PRIMÄR-Niveau heben oder zusätzliche Anforderungen aufdecken.
|
||||
6. **WPF-UI-Client stichprobenartig einbeziehen**, insbesondere Validierungslogik in ViewModels, da diese ggf. Geschäftsregeln enthält, die nicht im Backend dupliziert sind (Risiko für die Web-/SaaS-Neuimplementierung, wenn UI-only-Regeln übersehen werden).
|
||||
7. **Sales-Unterordner `Customers`, `CustomerAssets`, `Marketing`, `Support`** vertiefen — direkt angrenzend an die bereits gut abgedeckten Receipts, vermutlich mit hoher Anforderungsdichte pro analysiertem Dateiaufwand.
|
||||
8. **Konsolidierungspotenzial systematisch untersuchen**: Die aktuelle Iteration konnte mangels Breite kaum Redundanzen aufdecken; eine gezielte Suche nach mehrfach implementierten, fachlich gleichwertigen Validierungen (z. B. Kreditlimitprüfung an mehreren Belegarten, Rechteprüfungsmuster) wäre für die Zielsystem-Konsolidierung besonders wertvoll.
|
||||
|
||||
## 6. Zusammenfassung
|
||||
|
||||
Diese Iteration liefert eine **belastbare, aber bewusst schmale** Spezifikationsbasis für sieben Kernbereiche des c-entron-ERP (Belegwesen, Verträge/Abrechnung, Sicherheit/Rechte, Lizenzierung, Lager, EDI, E-Rechnung) mit insgesamt 19 StRS-, 20 SyRS- und 28 SwRS-Anforderungen, vollständiger Vorwärts-/Rückwärts-Traceability und einer einzigen offenen Hypothese. Der weit überwiegende Teil der Codebasis (>90 % der BL-Verzeichnisse nach Dateizahl, der komplette WPF-Client, alle externen API-Module, alle Deployment-/Betriebsartefakte) wurde **nicht** inhaltlich untersucht und ist explizit als Lücke dokumentiert, nicht stillschweigend ausgelassen.
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
# Glossar — Domänenbegriffe
|
||||
|
||||
Begriffe, die in StRS/SyRS/SwRS verwendet werden, mit Definition beim ersten fachlichen Auftreten. Deutsche Fachbegriffe sind führend; technische Bezeichner (Klassen, Tabellen, Felder) bleiben im Original.
|
||||
|
||||
| Begriff | Definition |
|
||||
|---|---|
|
||||
| **Beleg** | Sammelbegriff für alle sieben Geschäftsdokument-Typen des Verkaufsprozesses: Angebot (Offer), Auftrag (Order), Lieferschein (DeliveryList), Rechnung (Invoice), Gutschrift (CreditVoucher), Vertrag (Contract), Abholliste (PickupList). Technisch: gemeinsame Basis `ReceiptBase`. |
|
||||
| **I3D** | Primärschlüsselkonvention des Systems: jede Entität, die von `BaseEntity` erbt, besitzt ein Feld `I3D` als eindeutigen Identifikator (Analogon zu einer generischen Auto-Increment-ID). |
|
||||
| **Kopf/Position (*Kopf/*Pos)** | Legacy-Namenskonvention der Datenbanktabellen: `*Kopf` = Belegkopf (z. B. `RechKopf` = Rechnungskopf), `*Pos` = Belegpositionen/Zeilen (z. B. `RechPos` = Rechnungspositionen). |
|
||||
| **Belegstatus (ReceiptState)** | Zustand eines Belegs: `Active` ("offen"), `Completed` ("abgeschlossen"), `Canceled` ("storniert"). Siehe StRS-02/SyRS-02. |
|
||||
| **Versionstabelle (*Versions)** | Historisierungstabelle, die bei jeder Änderung eines Belegs eine vollständige Kopie des vorherigen Zustands aufnimmt (z. B. `AngKopfVersions`). Dient als Audit-Trail. Siehe StRS-03. |
|
||||
| **AnlageLog** | Zentrale, belegartübergreifende Protokolltabelle für Ereignisse an Belegen (Erstellung, Änderung, Abrechnung etc.), unterschieden über `AnlageArt` (Belegart-Kennzahl) und `AnlageI3D` (Referenz auf den konkreten Beleg). |
|
||||
| **ObjectKind / CentronObjectKindNumeric** | Numerische Kennzahl, die den Typ eines Geschäftsobjekts (u. a. Belegart) systemweit eindeutig identifiziert, z. B. für Logging (`AnlageArt`) oder Sortierung in der Belegsuche. |
|
||||
| **Vertrag / Kontingent** | Ein `ReceiptContract` bildet Wartungs-/Serviceverträge mit wiederkehrender Abrechnung ab; ein "Kontingent" ist ein vorab vereinbartes Volumen (Stunden oder Betrag), das im Vertragsverlauf verbraucht und bilanziert wird (`ContingentUsedHours`, `ContingentUsedAmount`). |
|
||||
| **RMM (Remote Monitoring and Management)** | Externes System (im Code als "Riverbird" bezeichnet), das Nutzungsstatistiken (z. B. Anzahl überwachter Server/Arbeitsplätze) liefert, die zur nutzungsbasierten Vertragsabrechnung herangezogen werden. |
|
||||
| **Kreditlimit (CreditLimit)** | Vom Fachbereich je Kunde festgelegter maximaler Wert offener Forderungen (netto oder brutto berechnet), dessen Überschreitung beim Speichern eines Belegs eine explizite Anwenderbestätigung erfordert. |
|
||||
| **Mahnstufe (DunningLevel)** | Eskalationsstufe im Mahnwesen (None, Level1, Level2, Level3) je nach Zahlungsverzug einer Rechnung. |
|
||||
| **Sichrech / Sichtrus / Sichmemb** | Legacy-Tabellen des Rechtesystems: `Sichrech` = Stammdaten der Rechte, `Sichtrus` = Zuordnung Recht↔Gruppe, `Sichmemb` = Zuordnung Benutzer↔Gruppe. |
|
||||
| **AppRight / AppGroup / AppUser** | Objektmodell-Pendants zu Sichrech/Sichtrus/Sichmemb auf NHibernate-Entity-Ebene. |
|
||||
| **Recht (UserRightsConst)** | Eine über eine eindeutige numerische ID (`I3D` in `Sichrech`) identifizierte, benannte Berechtigung, die einer Benutzergruppe zugewiesen werden kann; im Code ausschließlich über benannte Konstanten aus `UserRightsConst` referenziert. |
|
||||
| **2FA (Zwei-Faktor-Authentifizierung)** | Zusätzlicher, TOTP-basierter (zeitbasiertes Einmalpasswort) Prüfschritt bei der Anmeldung bzw. beim Zugriff auf sensible Funktionen, sofern für den Benutzer ein Schlüssel hinterlegt ist. |
|
||||
| **Passwort-Manager** | Lizenzpflichtiges Modul zur Verwaltung sensibler Kundenzugangsdaten (z. B. VPN-Zugänge) mit eigenem Rechte- und Freigabemodell (Sealing, Sichtbarkeits-/Editierrechte je Mitarbeiter). |
|
||||
| **Lizenz (License)** | Ein per GUID identifiziertes, vom zentralen Lizenzserver verwaltetes Merkmal, das eine Anwendung oder ein Einzelfeature freischaltet; kann zusätzlich mengen- (Count) und zeitbegrenzt (gültig bis Datum/Version) sein. |
|
||||
| **Anwendung (Application) vs. reine Lizenz** | "Applications" (`ApplicationKind.cs`) sind Lizenzen, die zusätzlich zum Login am Webservice berechtigen; alle anderen Lizenzen ("Only Licenses") schalten nur einzelne Funktionen frei. |
|
||||
| **EDI (Electronic Data Interchange)** | Automatisierter elektronischer Austausch von Geschäftsdokumenten (Auftragsbestätigung, Lieferavis, Rechnung) mit Lieferanten in standardisierten oder lieferantenspezifischen XML-Formaten. |
|
||||
| **Aktionspreis (ActionPrice)** | Zeitlich befristeter Sonderpreis eines Distributors/Herstellers für einen Artikel, der im Preisspiegel (Price Matrix) neben anderen Preisquellen angezeigt wird. |
|
||||
| **Preisspiegel (Price Matrix)** | Übersichtsansicht aller verfügbaren Einkaufspreisquellen für einen Artikel (u. a. ITscope, COP, NEOS, TradersGuide, EGIS, Artikel-Import, Aktionspreise). |
|
||||
| **ZUGFeRD / XRechnung** | Deutsche/europäische Standards für strukturierte elektronische Rechnungen (hybrides PDF+XML bzw. reines XML), die auf dem europäischen Rechnungsdatenmodell EN16931 basieren. |
|
||||
| **Reverse Charge** | Steuerliches Verfahren, bei dem die Umsatzsteuerschuld vom leistenden Unternehmen auf den Leistungsempfänger übergeht (§13b UStG); relevant für die Steuerkategorie "AE" in der E-Rechnung. |
|
||||
| **BaseEntity** | Abstrakte Basisklasse aller über NHibernate persistierten Entitäten; stellt das Primärschlüsselfeld `I3D` bereit. |
|
||||
| **DTO (Data Transfer Object)** | Objekt zur Datenübertragung zwischen Backend (BL) und Webservice/Clients; enthält keine Geschäftslogik, nur Daten (Konvention: Suffix `DTO`). |
|
||||
| **ILogic/BLLogic/WSLogic** | Architekturmuster: `ILogic`-Interface mit zwei Implementierungen — `BL{Modul}Logic` für Direktzugriff auf die Datenbank, `WS{Modul}Logic` für Zugriff über den Webservice. |
|
||||
| **Result / Response** | `Result`/`Result<T>` ist die interne Rückgabestruktur der Business-Logik-Schicht (Status Success/Error/Warning); `Response`/`Response<T>` ist das äquivalente, für die Webservice-API standardisierte Antwortformat. |
|
||||
| **Filiale (Branch)** | Organisatorische Einheit eines Mandanten; viele Belege und Rechte sind filialbezogen einschränkbar (`BranchI3D`, `OnlyOwnBranchRight`). |
|
||||
| **Mandator** | Oberste organisatorische Einheit (Unternehmen) im Mehrmandantenmodell des Systems, unterhalb derer Filialen (Branches) geführt werden. |
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Hypothesen — Sammlung offener, nicht eindeutig belegter Aussagen
|
||||
|
||||
Diese Datei sammelt alle mit `[HYPOTHESE]` markierten Aussagen aus StRS.md, SyRS.md und SwRS.md, jeweils mit der offenen Frage, die zur Bestätigung/Widerlegung geklärt werden müsste.
|
||||
|
||||
---
|
||||
|
||||
## H-01: Mahnstufenbasierte Auftragssperre (StRS-08 / SyRS-08 / SwRS-15)
|
||||
|
||||
**Aussage:** Das System sperrt die Erstellung neuer Aufträge (und ggf. weiterer Belegarten) für Kunden, deren Mahnstufe den in `AccountCustomer.LockOrderAfterDunningLevel` konfigurierten Schwellwert erreicht oder überschreitet.
|
||||
|
||||
**Warum Hypothese:** Es wurde ausschließlich die Zuweisung des Feldes aus einer globalen Einstellung gefunden (`AccountBL.cs`, Zeile 192: `customerData.LockOrderAfterDunningLevel = settings.GetInt(AppSettingsConst.CustomerAssetsLockedAfterDunningLevel);`). Eine Codestelle, die dieses Feld gegen den tatsächlichen `DunningLevel` eines Kunden vergleicht und daraus eine Sperre ableitet, wurde in den durchsuchten Bereichen (`ReceiptBL.cs`, `OrderSpecificLogic.cs`, `DunningBL.cs`, `DunningWebServiceBL.cs`) nicht gefunden.
|
||||
|
||||
**Fehlende Information zur Bestätigung:**
|
||||
- Vollständige Volltextsuche über die gesamte Codebasis (inkl. WPF.UI-ViewModels, gespeicherte Prozeduren/Named Queries, Reporting) nach lesendem Zugriff auf `LockOrderAfterDunningLevel`.
|
||||
- Rückfrage an den Fachbereich/Produktverantwortliche: Ist die Sperre rein informativ (Anzeige einer Warnung an den Sachbearbeiter) oder wird sie tatsächlich technisch durchgesetzt? Falls durchgesetzt: an welcher Stelle (UI-Vorabprüfung vs. Server-seitige Ablehnung)?
|
||||
- Da dies eine abrechnungs-/berechtigungsnahe Regel ist, gilt gemäß Auftrag die strengere Evidenzanforderung (mind. 1 PRIMÄR-Beleg) — diese ist aktuell nicht erfüllt.
|
||||
|
||||
**Risikoeinschätzung:** Hoch für die Zielsystem-Migration — falls die Regel im Altsystem nur implizit (z. B. durch manuelle Mitarbeiterdisziplin) durchgesetzt wird, muss dies im Neusystem explizit nachgebildet oder bewusst nicht übernommen werden.
|
||||
|
||||
---
|
||||
|
||||
## Hinweis zu weiteren, nicht in dieser Iteration vertieften Bereichen
|
||||
|
||||
Über die oben dokumentierte Hypothese hinaus wurden in dieser Iteration keine weiteren Aussagen mit `[HYPOTHESE]` markiert, da der Untersuchungsumfang bewusst auf Bereiche mit ausreichender PRIMÄR-Beleglage begrenzt wurde (siehe `Analysebericht.md`, Abschnitt "Abdeckung"). Für die **nicht vertieft analysierten Module** (siehe Analysebericht) wurden bewusst **keine** Anforderungen mit spekulativem Charakter erzeugt — das ist eine bewusste Auslassung, keine geprüfte und verworfene Hypothese. Diese Module sind daher nicht Bestandteil dieser Hypothesenliste, sondern der "Lücken"-Liste im Analysebericht.
|
||||
+363
@@ -0,0 +1,363 @@
|
||||
# Stakeholder Requirements Specification (StRS) — c-entron ERP
|
||||
|
||||
Erhebungsart: Reverse Requirements Engineering (statische Codeanalyse). Ebene gemäß ISO/IEC/IEEE 29148:2018: fachliche Sicht, Akteure, Geschäftsziele.
|
||||
|
||||
Hinweis zur Abdeckung: Diese StRS deckt die im Rahmen dieser Iteration vertieft analysierten Kernbereiche ab (Belegwesen/Sales, Verträge/Abrechnung, Sicherheit/Rechte, Lizenzierung, Lager, EDI, E-Rechnung). Sie ist **nicht vollständig** für die Gesamtcodebasis (siehe `Analysebericht.md`, Abschnitt Abdeckung).
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: StRS-01
|
||||
Titel: Einheitliche Belegverwaltung über den Verkaufsprozess
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Innendienst, System
|
||||
Vorbedingung: Ein Kunde/Interessent existiert im System.
|
||||
Fakt: Sieben Belegarten (Angebot, Auftrag, Lieferschein, Rechnung, Gutschrift, Vertrag, Abholliste) erben von einer gemeinsamen abstrakten Basisklasse `ReceiptBase` mit identischer Kopf-/Positionsstruktur (Nummer, Datum, Version, Status, Filiale, Währung, Empfänger, Adressfelder, Audit-Felder).
|
||||
Aussage: Das System soll den gesamten Verkaufsprozess (Angebot → Auftrag → Lieferschein → Rechnung, inkl. Gutschrift und Vertrag) als durchgängige, strukturell einheitliche Belegkette abbilden, sodass Folgebelege aus Vorgängerbelegen referenzierbar sind.
|
||||
Ergebnis: Jede Belegart wird konsistent mit denselben Kernattributen geführt; Folgebelege können auf Ursprungsbelege referenzieren (Belegkette).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs - Begründung: Abstrakte Basisklasse, von der alle sieben Belegentitäten erben; definiert die gemeinsame Kopf-Struktur verbindlich im Code.
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md (Tabelle Receipt Types Hierarchy, Zeilen 37-54) - Begründung: Entwicklerdokumentation bestätigt und benennt die konkrete Zuordnung Belegart→Entity→Tabelle→View.
|
||||
Prüfidee: Für jede der sieben Belegarten prüfen, dass Kopf-Objekt Number, Date, State, BranchI3D, CurrencyI3D, Receiver konsistent befüllt und persistiert wird; Test: Angebot anlegen → in Auftrag übernehmen → Referenz auf Ursprungsangebot prüfen.
|
||||
Tracelinks: SyRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-02
|
||||
Titel: Nachvollziehbarer Belegstatus (offen/abgeschlossen/storniert)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung
|
||||
Vorbedingung: Ein Beleg wurde angelegt.
|
||||
Fakt: Jeder Beleg führt ein Statusfeld `State` vom Typ `ReceiptState` mit den Werten Active ("offen"), Completed ("abgeschlossen") und Canceled ("storniert").
|
||||
Aussage: Das System soll für jeden Beleg jederzeit erkennbar machen, ob er offen, abgeschlossen oder storniert ist, und darf einen stornierten Beleg nicht mehr als bezahlt/unbezahlt umstellen lassen.
|
||||
Ergebnis: Anwender und nachgelagerte Prozesse (Mahnwesen, Buchhaltung) können anhand des Status entscheiden, ob ein Beleg noch bearbeitbar ist.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Definiert die drei einzig gültigen Statuswerte mit deutscher Anzeige-Beschreibung als Enum, das an `ReceiptBase.State` gebunden ist.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 4936-4937 - Begründung: Durchgesetzte Regel: `if (receipt.State == ReceiptState.Canceled) return Result...AsError("...wurde st[o]niert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden.")`.
|
||||
Prüfidee: Beleg stornieren, danach Versuch `SetPaid` aufzurufen → erwartete Fehlermeldung mit Code `DefaultMessageCodes.ErrorMessage`.
|
||||
Tracelinks: SyRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-03
|
||||
Titel: Revisionssichere Änderungshistorie von Belegen
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Buchhaltung, Revision/Wirtschaftsprüfung, System
|
||||
Vorbedingung: Ein Beleg wird gespeichert/geändert.
|
||||
Fakt: Für jede der sieben Belegarten existiert eine parallele *Versions-Tabelle (z. B. `AngKopfVersions`, `VertragPosVersions`), die laut Entwicklerdokumentation exakte 1:1-Kopien der Basistabellen sein müssen; das Kopieren erfolgt über den Mechanismus `AssetHeadDAO.SaveAssetVersion`.
|
||||
Aussage: Das System soll bei jeder Änderung eines Belegs eine vollständige, unveränderliche Kopie des vorherigen Zustands (Kopf und Positionen) in eine Versionstabelle schreiben, um Audit-Trails und Rollback-Fähigkeit zu ermöglichen.
|
||||
Ergebnis: Jede historische Belegversion bleibt nachträglich einsehbar und rekonstruierbar.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md, Abschnitt "Version Tables: 1:1 Copies of Original Tables" (Zeilen 145-204) - Begründung: Beschreibt Struktur, Pflichtfelder (OriginalI3D, KopfVersionsI3D) und den INSERT-Kopiervorgang aus Entwicklerhandbuch, das im Repository als verbindliche Wartungsanleitung geführt wird.
|
||||
- [KONTEXT] docs/reference/receipts/contracts-backend.md, Abschnitt "Contract Version Tables" (Zeilen 150-181) - Begründung: Bestätigt dasselbe Muster am konkreten Beispiel `VertragKopfVersions`/`VertragPosVersions` und warnt vor Laufzeitfehlern bei fehlender Spaltenparität.
|
||||
Prüfidee: Beleg zweimal ändern und speichern; prüfen, dass für jede Änderung ein neuer Datensatz mit inkrementierendem `OriginalI3D`-Bezug in der *Versions-Tabelle entsteht und alle Positionswerte identisch zum historischen Stand sind.
|
||||
Tracelinks: SyRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (Altsystem-Historisierung statt generischem Auditing-Framework)
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-04
|
||||
Titel: Übergreifende Belegsuche
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Kundenservice
|
||||
Vorbedingung: Beliebige Kombination aus Belegarten, Zeiträumen, Kunden, Beträgen soll durchsucht werden.
|
||||
Fakt: `ReceiptSearchWebServiceBL.SearchReceipts` delegiert an `ReceiptSearcher`, der für jede konfigurierte Belegart eine eigene SQL-Abfrage generiert, Rechte prüft und Ergebnisse vereinigt (Sortierung nach ObjectKind, dann Nummer absteigend).
|
||||
Aussage: Das System soll eine einzige Suchfunktion bereitstellen, mit der Anwender über alle Belegarten hinweg gleichzeitig nach Kunde, Zeitraum, Betrag, Zahlungsbedingung u. a. filtern können, wobei nur Belegarten durchsucht werden, für die der Anwender Anzeigerechte besitzt.
|
||||
Ergebnis: Ein einziger Suchaufruf liefert paginierte, rechtebereinigte Treffer über alle Belegarten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/WebServices/Sales/Receipts/ReceiptSearch/ReceiptSearcher.cs (laut docs/reference/receipts/receipt-search-architecture.md, Zeilen 74-99, mit Codeauszug) - Begründung: Zeigt den durchgesetzten Kontrollfluss inkl. Rechteprüfung `configuration.ShowRight` vor SQL-Ausführung.
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipt-search-architecture.md, Abschnitt "Filter Definition" (Zeilen 101-116) - Begründung: Benennt konkrete Filterfelder (SearchText, DateFrom/To, AccountI3D, ReceiptKinds, GrossPriceFrom/To) als vom Fachbereich nutzbare Suchkriterien.
|
||||
Prüfidee: Suche mit `ReceiptKinds = [Invoice]` und einem Kunden ohne Anzeigerecht für Rechnungen ausführen → 0 Treffer für diese Belegart trotz vorhandener Datensätze.
|
||||
Tracelinks: SyRS-04
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-05
|
||||
Titel: Wiederkehrende Vertragsabrechnung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsinnendienst, Buchhaltung, System (automatisierte Fakturierung)
|
||||
Vorbedingung: Ein Servicevertrag mit Kunde ist angelegt und aktiv.
|
||||
Fakt: `ReceiptContract` führt die Felder `BillingIntervalKind` (Daily/Monthly/Quarterly/Yearly), `BillingIntervalDuration`, `AutomatedBilling` sowie Kontingentfelder (`ContingentUsedHours`, `ContingentLimitValue` u. a.); `AutomaticFacturaBL.Contracts` erzeugt daraus automatisiert Rechnungen.
|
||||
Aussage: Das System soll Verträge mit konfigurierbarem Abrechnungsintervall automatisiert und wiederkehrend in Rechnungen überführen, inklusive Verrechnung von Kontingenten.
|
||||
Ergebnis: Fällige Verträge werden ohne manuellen Eingriff periodengerecht fakturiert; Kontingentverbrauch wird fortgeschrieben.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs (Felder laut docs/reference/receipts/contracts-backend.md, Zeilen 42-80) - Begründung: Entity-Felder sind die im Code durchgesetzte Datenstruktur für Abrechnungssteuerung.
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md, Abschnitt "Automated Billing Process" (Zeilen 315-332) - Begründung: Beschreibt den Ablauf (Fälligkeitsprüfung → Rechnungserzeugung → Kontingent-Update) auf Basis von `AutomaticFacturaBL`.
|
||||
Prüfidee: Vertrag mit `BillingIntervalKind=Monthly`, `AutomatedBilling=true` anlegen, Systemdatum auf Fälligkeitstag stellen, automatisierten Lauf ausführen → genau eine neue Rechnung mit Bezug `ContractI3D` entsteht.
|
||||
Tracelinks: SyRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-06
|
||||
Titel: Nutzungsbasierte Abrechnung über RMM-Integration
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Managed-Service-Provider-Kunde, System, externer RMM-Dienst ("Riverbird")
|
||||
Vorbedingung: Ein Vertrag ist für RMM-Abrechnung konfiguriert (`WhetherRMM` = true) und referenziert Artikel über `ContractArticleReferenzes`.
|
||||
Fakt: Während `CreateInvoiceToContractComplete` ruft `CheckRMMArticle` den externen RMM-Dienst über `RiverConnectionBL.GetContractBillingAmounts` auf; ist der Dienst nicht erreichbar UND werden RMM-Artikel erwartet, wird eine `RMMServiceUnavailableException` geworfen und die Rechnungserstellung abgebrochen.
|
||||
Aussage: Das System soll bei vertraglich vereinbarter nutzungsbasierter Abrechnung (z. B. Server-/Workstation-Zählung) Nutzungsdaten automatisiert vom externen RMM-System abrufen und in die Rechnung übernehmen; ist der Dienst nicht erreichbar, darf keine Rechnung mit unvollständigen Nutzungsdaten erzeugt werden.
|
||||
Ergebnis: Entweder wird die Rechnung mit korrekten RMM-Positionen erzeugt, oder die Erstellung wird kontrolliert abgebrochen (kein stiller Datenverlust).
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md, Codeauszug Zeilen 76-89 ("Error Handling for Service Unavailability") - Begründung: Zeigt die tatsächliche Ausnahmebehandlung im Code (`throw new RMMServiceUnavailableException(errorMsg)`), keine reine Beschreibung.
|
||||
- [KONTEXT] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md, Abschnitt "Placeholder Handling" (Zeilen 40-43) - Begründung: Erläutert den fachlichen Grund für den Platzhaltermechanismus `@@RMMArtikel@@` in der Rechnungsvorlage.
|
||||
Prüfidee: RMM-Dienst simulieren als nicht erreichbar, Vertrag mit RMM-Artikelreferenz abrechnen lassen → Rechnungserstellung schlägt mit definierter Fehlermeldung fehl, keine Teil-Rechnung wird gespeichert.
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-07
|
||||
Titel: Kreditlimitüberwachung für Kunden
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertriebsmitarbeiter, Buchhaltung/Controlling
|
||||
Vorbedingung: Ein Kunde hat ein Kreditlimit (`CreditLimit` > 0) konfiguriert und `CreditLimitCalculationKind` ist gesetzt (Netto oder Brutto).
|
||||
Fakt: `ReceiptBL` berechnet vor dem Speichern eines Belegs das bereits verbrauchte Limit über alle limitrelevanten Belegarten (`GetUsedLimitAmount`), vergleicht es mit dem verfügbaren Limit und zeigt bei Überschreitung einen Bestätigungsdialog (`ShowCustomerLimitExceededDialog`), sofern nicht `SaveAlthoughCustomerLimitExceeded` gesetzt ist.
|
||||
Aussage: Das System soll beim Speichern von limitrelevanten Belegen prüfen, ob das Kreditlimit des Kunden durch den aktuellen und alle offenen Belege überschritten wird, und den Anwender in diesem Fall zur expliziten Bestätigung auffordern, bevor der Beleg trotzdem gespeichert werden kann.
|
||||
Ergebnis: Kreditlimitüberschreitungen werden nicht unbemerkt gespeichert, sondern erfordern eine bewusste Anwenderentscheidung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 8646-8690 - Begründung: Durchgesetzte Berechnungslogik inkl. Abbruchbedingung und Dialogauslösung, direkt im Code nachvollzogen (kein Interpretationsspielraum).
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs, Zeilen 45-47 (`CreditLimit`, `CreditLimitAvailable`, `CreditLimitCalculationKind`) - Begründung: Persistente Datenfelder, auf denen die Berechnung in ReceiptBL operiert.
|
||||
Prüfidee: Kunde mit Limit 1000€ (Netto) anlegen, offene Belege mit Summe 900€ anlegen, neuen Beleg über 200€ ohne Override speichern → Bestätigungsdialog mit korrekt berechneter Differenz (100€) erscheint; mit `SaveAlthoughCustomerLimitExceeded=true` wird gespeichert.
|
||||
Tracelinks: SyRS-07
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-08
|
||||
Titel: Mahnstufenbasierte Auftragssperre
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Buchhaltung, Vertriebsmitarbeiter
|
||||
Vorbedingung: Für einen Kunden ist eine Mahnstufe erreicht und ein globaler Schwellwert (`AppSettingsConst.CustomerAssetsLockedAfterDunningLevel`) ist konfiguriert.
|
||||
Fakt: `AccountCustomer.LockOrderAfterDunningLevel` wird beim Anlegen eines Kunden aus der globalen Einstellung `CustomerAssetsLockedAfterDunningLevel` initialisiert (`AccountBL.cs`, Zeile 192). Eine Stelle, die dieses Feld tatsächlich zur Sperrung neuer Aufträge auswertet, konnte im untersuchten Code (`ReceiptBL.cs`, `OrderSpecificLogic.cs`) nicht gefunden werden.
|
||||
Aussage: [HYPOTHESE] Das System soll die Erstellung neuer Aufträge (und ggf. weiterer Belegarten) für Kunden sperren, deren Mahnstufe den konfigurierten Schwellwert erreicht oder überschreitet.
|
||||
Ergebnis: [HYPOTHESE] Ein Kunde oberhalb der konfigurierten Mahnstufe kann keine neuen Aufträge mehr auslösen, bis die offenen Forderungen beglichen sind.
|
||||
Belege:
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Accounts/AccountBL.cs, Zeile 192 - Begründung: Zeigt nur die Initialisierung des Feldes aus einer globalen Einstellung, nicht dessen Durchsetzung an einer Sperrstelle.
|
||||
- [KONTEXT] src/backend/Centron.Entities/Entities/Accounts/AccountCustomer.cs, Zeile 25 (`LockOrderAfterDunningLevel`) - Begründung: Bestätigt Existenz und Datentyp des Feldes, belegt aber keine Geschäftsregel.
|
||||
Prüfidee: Codestellen suchen, die `LockOrderAfterDunningLevel` lesend mit dem tatsächlichen `DunningLevel` eines Kunden vergleichen (z. B. in Order-/DeliveryList-SpecificLogic oder UI-ViewModels); falls keine gefunden wird, mit Fachbereich klären, ob die Sperre nur UI-seitig/manuell umgesetzt ist.
|
||||
Tracelinks: SyRS-08
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-09
|
||||
Titel: Rollenbasierte Zugriffssteuerung
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Administrator (Rechteverwaltung), alle Anwender, System
|
||||
Vorbedingung: Benutzer ist angemeldet und einer oder mehreren Benutzergruppen zugeordnet.
|
||||
Fakt: Rechte sind in der Tabelle `Sichrech` definiert, Gruppenzuordnung über `Sichtrus`/`Sichmemb`; `AppRightsBL.CheckRightsFromUser` prüft per parametrisiertem SQL-Join, welche der angefragten Rechte einem Benutzer über seine Gruppenmitgliedschaften zustehen.
|
||||
Aussage: Das System soll jede sicherheitsrelevante Aktion (Anlegen, Ändern, Löschen, Anzeigen von Geschäftsobjekten sowie Modulzugriff) gegen ein gruppenbasiertes Berechtigungsmodell prüfen, bevor die Aktion ausgeführt wird.
|
||||
Ergebnis: Nur Benutzer mit passendem Recht (über ihre Gruppen) können die jeweilige Aktion ausführen; fehlende Rechte führen zu einer definierten Fehlermeldung statt stiller Ausführung.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Zeilen 89-135 (`CheckRightsFromUser`, `CheckWebRightsFromUser`) - Begründung: Durchgesetzte, parametrisierte SQL-Abfrage gegen `Sichtrus`/`Sichmemb`/`WebAccountsRights`; direkte Codequelle der Rechteprüfung.
|
||||
- [SEKUNDÄR] docs/guides/development/check-userrights.md, Zeilen 22-43 - Begründung: Entwicklerleitfaden mit Codebeispiel aus `AccountBL.cs`, das den vorgeschriebenen Prüf- und Ablehnungsmechanismus ("Fehlende Rechte um Accounts zu erstellen") demonstriert.
|
||||
Prüfidee: Benutzer ohne Recht `CREATE_CUSTOMER` versucht Kunde anzulegen → `AccountBL` liefert `Result.AsError("Fehlende Rechte um Accounts zu erstellen")`, kein Datensatz wird angelegt.
|
||||
Tracelinks: SyRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-10
|
||||
Titel: Schutz sensibler Zugangsdaten durch Passwort-Manager und Zwei-Faktor-Authentifizierung
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Mitarbeiter mit Zugriff auf Kundenzugangsdaten, Administrator
|
||||
Vorbedingung: Kunde besitzt hinterlegte Zugangsdaten (z. B. VPN-Zugänge) im Passwort-Manager-Modul.
|
||||
Fakt: `PasswordManagerBL` prüft vor Herausgabe von Rechte-/Zugangsdaten explizit `LicenseManager.Instance.HasLicense(LicenseGuids.PasswordManager)`. `TwoFactorAuthenticationBL.ValidateAuthenticationPin` validiert eine TOTP-PIN gegen einen je Mitarbeiter hinterlegten Schlüssel über `GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin`.
|
||||
Aussage: Das System soll den Zugriff auf im Passwort-Manager hinterlegte, sensible Kundenzugangsdaten an eine gültige Lizenz binden und zusätzlich optional durch eine Zwei-Faktor-Authentifizierung (TOTP) absichern können.
|
||||
Ergebnis: Ohne gültige Lizenz ist kein Zugriff auf Passwort-Manager-Funktionen möglich; ist 2FA für einen Benutzer hinterlegt, ist eine gültige PIN zusätzlich zum regulären Login erforderlich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/PasswordManager/PasswordManagerBL.cs, Zeilen 92-96 - Begründung: Durchgesetzte Lizenzprüfung mit definiertem Fehlercode `DefaultMessageCodes.LicenseNotFound` vor Datenzugriff.
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Zeilen 43-54 (`ValidateAuthenticationPin`) - Begründung: Durchgesetzte PIN-Validierung inkl. Fehlermeldung bei fehlendem Schlüssel bzw. ungültiger PIN.
|
||||
Prüfidee: Benutzer ohne Passwort-Manager-Lizenz ruft `GetPasswordManagerCustomersEmployeesRights` auf → Fehler "Sie besitzen keine Lizenz für den Passwort-Manager."; Benutzer mit hinterlegtem 2FA-Schlüssel gibt falsche PIN ein → Fehler "Die eingegebene PIN ist ungültig!".
|
||||
Tracelinks: SyRS-10, SyRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-11
|
||||
Titel: Modulare, zählbare und zeitlich begrenzte Lizenzierung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Vertrieb (c-entron-Anbieter), Administrator beim Kunden, System
|
||||
Vorbedingung: Kunde hat einen Lizenzvertrag mit dem Software-Anbieter.
|
||||
Fakt: Jede Lizenz ist ein GUID (`LicenseGuids.cs`) mit optionalen Attributen Anzahl (`count`), Ablaufdatum und Ablaufversion; `LicenseManager` bietet `HasLicense(Guid)` und `GetLicenseCount(Guid)` als zentrale Prüf-API; Anwendungen, die sich am Webservice anmelden dürfen, sind separat in `ApplicationKind.cs` gepflegt.
|
||||
Aussage: Das System soll Programmfunktionen (einzelne Features und ganze Anwendungen) davon abhängig machen, ob der Kunde eine entsprechende, gültige und ggf. mengenmäßig ausreichende Lizenz besitzt.
|
||||
Ergebnis: Nicht lizenzierte Funktionen sind für den Kunden nicht nutzbar bzw. mengenmäßig begrenzt; nicht lizenzierte Anwendungen können sich nicht am Webservice anmelden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, Zeilen 26-40 (Interface `ILicenseManager`) - Begründung: Definiert die im gesamten Backend verwendete, verbindliche Prüf-API (`HasLicense`, `GetLicenseCount`, `CheckLicense`).
|
||||
- [SEKUNDÄR] docs/reference/security/licensing-system.md, Zeilen 1-101 - Begründung: Entwicklerdokumentation mit Codebeispielen zur Nutzung der API und Erläuterung der Unterscheidung "Applications" vs. "Only Licenses".
|
||||
Prüfidee: Feature mit Lizenz-GUID ohne zugeordnete Lizenz beim Kunden aufrufen → `HasLicense` liefert `false`, UI blendet Funktion aus (Beispiel Passwort-Manager, siehe StRS-10).
|
||||
Tracelinks: SyRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-12
|
||||
Titel: Automatisierter Lieferanten-Belegaustausch (EDI)
|
||||
Ebene: StRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: Einkauf, System, externe Distributoren (ALSO, Alltron, Herweck, Komsa, OpenTrans-Partner)
|
||||
Vorbedingung: Ein EDI-Lieferant ist über `SupplierEdiConfigurations` konfiguriert (FTP/SFTP-Zugang, Format).
|
||||
Fakt: `SupplierEdiBL` ist als partielle Klasse je Lieferantenformat organisiert (`SupplierEdiBL.Also.cs`, `.AlsoCH.cs`, `.Alltron.cs`, `.Herweck.cs`, `.Komsa.cs`, `.Opentrans.cs`); `ApplyDistriToCentron` dispatcht nach `EdiDataType` und `EDIConnectionObjectKind` (Order/OrderResponse/Delivery/Invoice).
|
||||
Aussage: Das System soll Auftragsbestätigungen, Lieferavise und Rechnungen mehrerer IT-Distributoren automatisiert in unterschiedlichen lieferantenspezifischen Formaten einlesen, auf bestehende c-entron-Aufträge abgleichen und Belege (Lieferschein, Rechnung) daraus erzeugen.
|
||||
Ergebnis: Eingehende EDI-Dateien werden ohne manuelle Nacherfassung in c-entron-Belege überführt; nicht zuordenbare Datensätze lösen eine Benutzerbenachrichtigung aus.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md, Tabelle "Document Types Supported" (Zeilen 110-123) und Codeauszug `ApplyDistriToCentron` (Zeilen 91-106) - Begründung: Entwicklerdokumentation mit Methodensignatur aus dem Quellcode; belegt Dispatch-Mechanismus und Format-Abdeckung je Lieferant.
|
||||
Prüfidee: Test-EDI-Datei eines unterstützten Lieferanten (z. B. Alltron-Lieferavis) einspielen → zugehöriger c-entron-Auftrag wird um Lieferinformationen (Sendungsverfolgung, Seriennummern) ergänzt, Verarbeitungsstatus wird in `EDILogBL` protokolliert.
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-13
|
||||
Titel: Verwaltung zeitlich begrenzter Aktionspreise
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Einkauf, Vertriebsmitarbeiter (Preisspiegel)
|
||||
Vorbedingung: Ein Artikel existiert im Artikelstamm.
|
||||
Fakt: Tabelle `HerstellerArtikAktionspreis` / Entity `ActionPrice` speichert Distributor, Preis, Gültigkeitszeitraum (`GueltigAb`/`GueltigBis`) je Artikel; `ActionPriceBL` validiert beim Speichern Pflichtfeld Distributor und `EffectiveFrom ≤ EffectiveUntil`.
|
||||
Aussage: Das System soll es erlauben, zeitlich befristete Sonderpreise von Distributoren/Herstellern je Artikel zu erfassen und im Preisspiegel nur dann anzuzeigen, wenn das aktuelle Datum innerhalb des Gültigkeitszeitraums liegt.
|
||||
Ergebnis: Anwender sehen im Preisspiegel ausschließlich aktuell gültige Aktionspreise; abgelaufene oder zukünftige Preise werden ausgeblendet.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/actionprice-system.md, Abschnitt "Validation Rules" (Zeilen 301-312) und "Display Rules" - Begründung: Dokumentiert die tatsächliche Filterbedingung `EffectiveFrom.StartOfDay() <= DateTime.Now && EffectiveUntil >= DateTime.Now` sowie die Pflichtfeldprüfung, mit Verweis auf konkrete Klassen (`ActionPriceBL`, `PriceMatrixViewModel`).
|
||||
Prüfidee: Aktionspreis mit `EffectiveUntil` in der Vergangenheit anlegen → erscheint nicht im Preisspiegel; Versuch, Aktionspreis ohne Distributor zu speichern → Validierungsfehler.
|
||||
Tracelinks: SyRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-14
|
||||
Titel: Kontrollierte Lagerbestandsbuchung
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Lagermitarbeiter, Einkauf
|
||||
Vorbedingung: Artikel ist im Lager geführt (Haupt- oder Nebenlager).
|
||||
Fakt: `UserRightsConst.Purchase.StockList` definiert granulare Rechte für Bestandsvorgänge, u. a. `BOOK_TO_STOCK`, `BOOK_FROM_STOCK`, `TRANSFER_STOCK`, `SerialAdministration` und explizit `BOOK_ARTICLE_STOCK_INTO_NEGATIVE`; `ArticleBL` prüft diese Rechte vor Anzeige/Ausführung der jeweiligen Bestandsfunktion.
|
||||
Aussage: Das System soll Zubuchung, Abbuchung, Umlagerung und insbesondere die Buchung eines Artikels in einen negativen Bestand jeweils an ein eigenes, separat vergebbares Benutzerrecht binden.
|
||||
Ergebnis: Nur berechtigte Benutzer können Bestände negativ buchen; alle anderen Bestandsoperationen sind ebenfalls granular rechtegesteuert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Zeilen 99-123 - Begründung: Zeigt die durchgesetzte Rechteprüfung (`HasUserRight`) für jede einzelne Bestandsoperation inkl. der spezifischen Negativbuchungs-Berechtigung.
|
||||
Prüfidee: Benutzer ohne `BOOK_ARTICLE_STOCK_INTO_NEGATIVE` versucht Abbuchung, die den Bestand unter 0 bringen würde → Aktion wird verweigert; Benutzer mit Recht kann die Buchung durchführen.
|
||||
Tracelinks: SyRS-15
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-15
|
||||
Titel: Gesetzeskonforme elektronische Rechnungsstellung (ZUGFeRD/XRechnung)
|
||||
Ebene: StRS
|
||||
Typ: funktional
|
||||
Akteur: Buchhaltung, öffentliche Auftraggeber (XRechnung-Pflicht), System
|
||||
Vorbedingung: Eine Rechnung oder Gutschrift ist vollständig erfasst.
|
||||
Fakt: `InvoiceZugferdBL` erzeugt ZUGFeRD-1.0/2.0/2.1- bzw. XRechnung-1.2/2.0/2.2/2.3.1/3.0.1-konforme XML-Dateien aus Rechnungsdaten; das System validiert dabei, dass die Summe der Positionsnettobeträge dem Kopf-Nettobetrag entspricht (Toleranz ±3,00) und weist Steuerkategorien (S/E/K/G/AE) nach klar definierten Regeln zu.
|
||||
Aussage: Das System soll Rechnungen und Gutschriften in strukturierten, normkonformen XML-Formaten (ZUGFeRD/XRechnung) exportieren können, wobei rechnerische Inkonsistenzen zwischen Kopf- und Positionssummen außerhalb einer definierten Toleranz den Export mit einem Fehler abbrechen.
|
||||
Ergebnis: Rechtskonforme E-Rechnungen können an Behörden/Geschäftspartner übermittelt werden; fehlerhafte Rechnungen werden vor Versand erkannt.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/zugferd-field-mapping.md, Abschnitt "Validation" (Zeilen 218-221) und "Tax Category Codes" (Zeilen 173-184) - Begründung: Dokumentiert mit Verweis auf konkrete Codezeilen (`InvoiceZugferdBL.cs:117-158`, `:1369-1400`) die tatsächlich im Code implementierten Toleranz- und Steuerkategorie-Regeln.
|
||||
Prüfidee: Rechnung mit manipulierter Positionssumme (Abweichung > 3,00 vom Kopfbetrag) exportieren → Export schlägt mit Fehler fehl; Abweichung ≤ 3,00 → Export mit Warnung und korrigiertem Wert.
|
||||
Tracelinks: SyRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-16
|
||||
Titel: Schutz von Testumgebungen vor versehentlichem Kundenkontakt
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional (Zuverlässigkeit/Betriebssicherheit)
|
||||
Akteur: Entwickler, System (DEBUG-Build)
|
||||
Vorbedingung: Eine E-Mail wird aus einer DEBUG-Build-Instanz des Systems versendet.
|
||||
Fakt: `DeveloperSecurity.Email.ValidateAddress` ersetzt in DEBUG-Builds (`AllowSendingEmailToExternalAddresses = DebugHelper.IsReleaseBuild()`, also `false` im Debug-Build) jede E-Mail-Adresse, die nicht auf die Domain `nexoware.com` endet, durch `test@nexoware.com`.
|
||||
Aussage: Das System soll in Entwicklungs-/Testbuilds verhindern, dass E-Mails versehentlich an echte externe Kundenadressen versendet werden, indem es solche Adressen automatisch durch eine interne Testadresse ersetzt.
|
||||
Ergebnis: In DEBUG-Builds erreichen ausgehende Mails nie externe (Kunden-)Adressen; interne Adressen bleiben unverändert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Common/DeveloperSecurity.cs, Zeilen 8-46 - Begründung: Vollständige, durchgesetzte Implementierung der Ersetzungslogik inklusive Bedingung für Release-Build.
|
||||
- [KONTEXT] docs/reference/security/developer-security.md - Begründung: Bestätigt Zweck und Aktivierungsbedingung ("nur in DEBUG-Builds aktiv") aus Entwicklersicht.
|
||||
Prüfidee: In DEBUG-Build eine Mail an "kunde@fremdefirma.de" auslösen → tatsächlicher Empfänger ist "test@nexoware.com"; Mail an "kollege@nexoware.com" bleibt unverändert.
|
||||
Tracelinks: SyRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-17
|
||||
Titel: Wartbare, austauschbare Systemarchitektur (Direktzugriff vs. Webservice)
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional (Wartbarkeit/Übertragbarkeit)
|
||||
Akteur: Entwicklerteam, Betrieb
|
||||
Vorbedingung: Ein Client (WPF-Anwendung, Outlook-Add-in, mobile Anwendung) benötigt Zugriff auf Geschäftsdaten.
|
||||
Fakt: Jedes fachliche Modul implementiert verpflichtend ein `ILogic`-Interface mit zwei Implementierungen: `BL{Modul}Logic` (Direktzugriff via NHibernate/DB) und `WS{Modul}Logic` (Zugriff über REST-Webservice); beide liefern `Result<T>` bzw. `Task<Result<T>>` in identischer Signatur.
|
||||
Aussage: Das System soll für jedes fachliche Modul sowohl einen direkten Datenbankzugriff als auch einen Webservice-basierten Zugriff über eine identische Schnittstelle anbieten, sodass Clients ohne Codeänderung zwischen beiden Zugriffsarten wechseln können.
|
||||
Ergebnis: Ein und dieselbe Client-Logik funktioniert unverändert sowohl im LAN-Direktzugriff als auch über den Webservice (Cloud-/Remote-Betrieb).
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md, Abschnitt "Dual Implementation Architecture" (Zeilen 36-95) - Begründung: Entwicklerdokumentation mit vollständigen Codebeispielen für Interface, BL- und WS-Implementierung als verbindliche Architekturvorgabe ("MUST implement both").
|
||||
Prüfidee: Ein Modul mit beiden Implementierungen identifizieren (z. B. `IAccountContractsLogic`) und prüfen, dass beide Implementierungen dieselbe Methode mit identischer Rückgabestruktur anbieten.
|
||||
Tracelinks: SyRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-18
|
||||
Titel: Schutz vor unautorisiertem Datenzugriff und SQL-Injection
|
||||
Ebene: StRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System, Angreifer (Bedrohungsmodell), Endanwender
|
||||
Vorbedingung: Benutzereingaben fließen in eine Datenbankabfrage ein (z. B. Belegsuche).
|
||||
Fakt: Die Belegsuche (`ReceiptSearcher`) verwendet ausschließlich parametrisierte Named-Query-Parameter (`NamedQueryParameter`) statt String-Konkatenation von Benutzereingaben in SQL-Statements; Berechtigungsprüfungen (`ShowRight`, `OnlyOwnRight`, `OnlyOwnBranchRight`) erfolgen vor Ausführung der Query.
|
||||
Aussage: Das System soll bei dynamisch zusammengesetzten SQL-Abfragen Benutzereingaben ausschließlich über parametrisierte Platzhalter einbinden und den Datenzugriff zusätzlich durch rechte- und filialbasierte Vorfilterung einschränken.
|
||||
Ergebnis: Benutzereingaben können keine SQL-Injection auslösen; Anwender sehen nur Daten, für die ihre Rechte/Filialzugehörigkeit dies zulässt.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipt-search-architecture.md, Codeauszug Zeilen 162-182 (`CreateSqlStatementAndParameters`) - Begründung: Zeigt den tatsächlichen Mechanismus `parameters.Add(new NamedQueryParameter(...))` statt Stringverkettung, direkt aus dem Quellcode zitiert.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Zeilen 95-111 - Begründung: Parametrisierte Query-Konstruktion (`NamedQueryParameter("UserI3D", ...)`) auch im Rechtemodul, als weiterer Beleg für ein durchgängiges Muster.
|
||||
Prüfidee: Suchfilter mit SQL-Metazeichen (`'; DROP TABLE ...`) in `SearchText` befüllen → Query wird als Parameterwert behandelt, keine strukturelle Änderung der Abfrage; Penetrationstest mit automatisiertem SQLi-Scanner auf Such-Endpunkt.
|
||||
Tracelinks: SyRS-19
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: StRS-19
|
||||
Titel: Deutschsprachige, lokalisierte Benutzeroberfläche
|
||||
Ebene: StRS
|
||||
Typ: nicht-funktional (Benutzbarkeit)
|
||||
Akteur: Endanwender (primär deutschsprachiger Markt)
|
||||
Vorbedingung: Anwender öffnet eine beliebige Programmoberfläche.
|
||||
Fakt: Entwicklerrichtlinie schreibt vor, dass alle UI-Labels, Benutzermeldungen und Fehlermeldungen auf Deutsch verfasst werden; deutschsprachige Ressourcen liegen als Basis-Resx (`LocalizedStrings.resx`), englische Übersetzungen in `LocalizedStrings.en.resx`.
|
||||
Aussage: Das System soll alle benutzersichtbaren Texte primär in deutscher Sprache anbieten und Fehlermeldungen konsistent in deutscher, fachlich verständlicher Sprache formulieren.
|
||||
Ergebnis: Endanwender im deutschsprachigen Markt erhalten eine vollständig deutschsprachige Oberfläche; eine englische Alternativsprache steht über separate Ressourcen zur Verfügung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md, Abschnitt "Localization and UI Language Requirements" (Zeilen 114-141) - Begründung: Explizite, im Repository dokumentierte Entwicklungsrichtlinie ("German-First Language Policy").
|
||||
- [KONTEXT] Beispiele deutschsprachiger Fehlermeldungen im Code, u. a. "Fehlende Rechte um Accounts zu erstellen" (AccountBL.cs), "Die eingegebene PIN ist ungültig!" (TwoFactorAuthenticationBL.cs) - Begründung: Bestätigt die tatsächliche Umsetzung der Richtlinie an mehreren untersuchten Stellen.
|
||||
Prüfidee: Stichprobenprüfung von 20 zufällig gewählten Fehlermeldungen/UI-Strings auf deutsche Sprache und Vorhandensein einer `.en.resx`-Übersetzung.
|
||||
Tracelinks: SyRS-20
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+512
@@ -0,0 +1,512 @@
|
||||
# Software Requirements Specification (SwRS) — c-entron ERP
|
||||
|
||||
Ebene gemäß ISO/IEC/IEEE 29148:2018: Komponenten, Datenmodelle, software-interne Regeln. Jede Anforderung konkretisiert eine SyRS-Anforderung auf Ebene konkreter Klassen/Methoden/Tabellen.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: SwRS-01
|
||||
Titel: ReceiptBase als polymorphe Basisklasse aller Belegköpfe
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System (NHibernate/BL)
|
||||
Vorbedingung: -
|
||||
Fakt: `Centron.Data.Entities.Sales.Receipts.ReceiptBase : BaseEntity, IReceiptBase` deklariert 26 virtuelle Properties sowie 4 abstrakte Methoden (`GetReceiptItems`, `SetReceiptItems`, `AddItem`, `RemoveItem`) und die abstrakte Property `ReceiptKind : CentronObjectKindNumeric`.
|
||||
Aussage: Die Klasse `ReceiptBase` soll als einzige gemeinsame Basisklasse für alle sieben Belegkopf-Entitäten dienen und darf von konkreten Belegarten nur erweitert, nicht in ihrer Grundstruktur verändert werden.
|
||||
Ergebnis: Neue Belegarten werden strukturell konsistent zu bestehenden Belegarten implementiert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Zeilen 1-72 - Begründung: Vollständiger Klassencode.
|
||||
Prüfidee: Vererbungshierarchie aller Klassen mit Namensmuster `Receipt*` per Reflection prüfen: alle erben transitiv von `ReceiptBase`.
|
||||
Tracelinks: SyRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-02
|
||||
Titel: Duale Tabellen-/View-Architektur je Belegart (deutsche Legacy-Tabellen + englische Views)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System (NHibernate-Mapping, Legacy-Repository)
|
||||
Vorbedingung: -
|
||||
Fakt: Jede Belegart hat eine deutsche Kopf-Tabelle (`AngKopf`, `AufKopf`, `LiefKopf`, `RechKopf`, `VertragKopf`, `GutKopf`, `AbholKopf`) mit zugehöriger Positions-Tabelle (`*Pos`) sowie eine englischsprachige View (`Offers`, `Orders`, ...) für den lesenden C#-Zugriff; Speichern erfolgt jedoch NICHT über die moderne Entity-Mapping-Schicht, sondern über legacy `SaveReceipt*Repository`-Klassen, die `SynchronizeReceiptData`/`SynchronizeReceiptItemData` in die `*Kopf`/`*Pos`-Tabellen schreiben.
|
||||
Aussage: Jede neue oder geänderte persistierte Eigenschaft eines Belegs muss sowohl in der Basistabelle, der zugehörigen View als auch im entsprechenden `SaveReceipt*Repository` synchronisiert werden; ein alleiniges Hinzufügen zur View/Entity-Mapping führt dazu, dass der Wert zwar geladen, aber beim Speichern verworfen wird.
|
||||
Ergebnis: Datenverlust bei neuen Feldern wird vermieden, wenn der dokumentierte Prozess eingehalten wird; wird er nicht eingehalten, ist ein stiller Datenverlust beim Speichern die Folge (dokumentiertes Risiko).
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipts-backend-architecture.md, Abschnitt "Critical Save Warning" (Zeilen 190) - Begründung: Explizite Warnung im Entwicklerhandbuch, die auf einen tatsächlich beobachteten/vermiedenen Fehlermodus hinweist ("the value may load correctly from the view but will not be persisted on save").
|
||||
Prüfidee: Neues Feld nur in View + Entity ergänzen (nicht im Repository) → Wert wird nach Speichern+Neuladen NICHT persistiert; Regressionstest als Vorlage für künftige Feldänderungen einrichten.
|
||||
Tracelinks: SyRS-01, SyRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (Doppelte Persistenzpfade als Altlast der Migration von Delphi-Legacy-System)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-03
|
||||
Titel: ReceiptState-Enum mit fest definierten drei Werten
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `public enum ReceiptState { Active = 1 [„offen“], Completed = 2 [„abgeschlossen“], Canceled = 3 [„storniert“] }` in `Centron.Interfaces.Sales.Receipts.ReceiptState`.
|
||||
Aussage: Das Feld `ReceiptBase.State` darf ausschließlich einen der drei Werte 1/2/3 annehmen; jede Erweiterung um weitere Zustände erfordert eine Anpassung von `ReceiptStateExtensions.GetReceiptStateString` und aller Schalterlogiken, die auf diesem Enum `switch`en.
|
||||
Ergebnis: Konsistente, sprachlich definierte Statuswerte über das gesamte System.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs, Zeilen 6-28 - Begründung: Vollständiger Enum- und Switch-Code.
|
||||
Prüfidee: Compile-Test: `default: throw new ArgumentOutOfRangeException()` in `GetReceiptStateString` deckt auf, wenn ein neuer Enum-Wert ohne Anpassung eingeführt wird.
|
||||
Tracelinks: SyRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-04
|
||||
Titel: Sperre der Zahlungsstatus-Änderung für stornierte Belege
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptBL.SetReceiptPaidStatus o. ä.)
|
||||
Vorbedingung: `receipt.State == ReceiptState.Canceled`.
|
||||
Fakt: `if (receipt.State == ReceiptState.Canceled) return Result<IReceiptBase>.AsError($"Der Beleg {receiptI3D} ({receiptKind.GetDescription()}) wurde stoniert und kann daher nicht als bezahlt oder nicht bezahlt eingestellt werden.", DefaultMessageCodes.ErrorMessage);` — beachte den Tippfehler "stoniert" statt "storniert" in der produktiven Fehlermeldung.
|
||||
Aussage: Die Methode zum Setzen des Zahlungsstatus soll für stornierte Belege konsequent einen Fehler mit `DefaultMessageCodes.ErrorMessage` liefern, bevor Zahlungsfelder verändert werden; zusätzlich wird vor jeder Statusänderung die optimistische Sperre (`ConcurrencyControlGuid`) geprüft.
|
||||
Ergebnis: Kein stornierter Beleg kann nachträglich einen Zahlungsstatus erhalten; gleichzeitige Änderungen durch zwei Benutzer werden über die Concurrency-Prüfung erkannt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 4936-4940 - Begründung: Exakter, zitierter Code inkl. des Rechtschreibfehlers, der die Korrektheit des Zitats belegt.
|
||||
Prüfidee: Fehlermeldungstext exakt gegen Testfall abgleichen (inkl. Tippfehler-Erkennung als Regressionsschutz gegen unbeabsichtigte Textänderung); parallele Änderung mit veraltetem `ConcurrencyControlGuid` → Fehler `ChangedByOtherInstance`.
|
||||
Tracelinks: SyRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-05
|
||||
Titel: Struktur der Versionstabellen (OriginalI3D, KopfVersionsI3D)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System (AssetHeadDAO)
|
||||
Vorbedingung: -
|
||||
Fakt: Versionstabellen enthalten alle Spalten der Basistabelle außer `I3D`, zusätzlich `OriginalI3D` (Verweis auf Ursprungsdatensatz) und bei Positionstabellen zusätzlich `KopfVersionsI3D` (Verweis auf die zugehörige Kopf-Version).
|
||||
Aussage: Jede *KopfVersions-/*PosVersions-Tabelle muss exakt die Spalten ihrer Basistabelle (minus I3D) plus die beiden genannten Referenzspalten enthalten; Abweichungen führen laut Dokumentation zu Laufzeitfehlern beim automatischen Feldlisten-Aufbau (`DoGetFieldList()`).
|
||||
Ergebnis: Vollständige, strukturkonsistente Versionierung ohne manuelle Spaltenzuordnung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md, Zeilen 147-188 - Begründung: Beschreibt Pflichtstruktur und den Fehlermodus bei Abweichung mit Verweis auf `DoGetFieldList()`.
|
||||
Prüfidee: Automatisiertes Schema-Diff-Skript zwischen jeder `*Kopf`/`*Pos`-Tabelle und ihrer `*Versions`-Entsprechung als CI-Check.
|
||||
Tracelinks: SyRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-06
|
||||
Titel: Kopiervorgang AssetHeadDAO.SaveAssetVersion
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Ein Beleg wird gespeichert und eine neue Version soll erzeugt werden.
|
||||
Fakt: Kopiermechanismus per INSERT...SELECT: Kopf zuerst (`INSERT INTO AngKopfVersions (...) SELECT ..., I3D AS OriginalI3D FROM AngKopf WHERE I3D=@receiptId`), danach alle zugehörigen Positionen mit Bezug auf die neu erzeugte Kopf-Versions-I3D.
|
||||
Aussage: Der Kopiervorgang soll für jede Belegänderung genau einen Kopf-Versionsdatensatz und für jede zugehörige Position genau einen Positions-Versionsdatensatz erzeugen, wobei die Positions-Versionen korrekt auf den neuen Kopf-Versionsdatensatz verweisen (nicht auf den ursprünglichen Kopf).
|
||||
Ergebnis: Eine vollständige, referenziell korrekte Historie pro Speichervorgang.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md, Zeilen 160-172 (SQL-Beispiel) - Begründung: Zeigt konkretes SQL-Muster des Kopiervorgangs.
|
||||
Prüfidee: Beleg mit 5 Positionen zweimal ändern → 2 Kopf-Versionsdatensätze, 10 Positions-Versionsdatensätze mit korrektem `KopfVersionsI3D`-Bezug je Änderungszeitpunkt.
|
||||
Tracelinks: SyRS-03
|
||||
Konsolidierung: Kandidat: SwRS-05 (gemeinsame Testbasis Schema+Kopiervorgang)
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-07
|
||||
Titel: Dynamische SQL-Generierung je Belegart-Suchkonfiguration
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptSearcher)
|
||||
Vorbedingung: Suchanfrage mit `ReceiptSearchFilter` liegt vor.
|
||||
Fakt: `ReceiptSearcher.CreateSqlStatementAndParameters` beginnt mit `configuration.GetBaseSelectStatement(filter)`, hängt für jedes gesetzte Filterfeld das zugehörige `*WhereStatement` der jeweiligen `ReceiptSearchConfiguration`-Unterklasse an; ist das WHERE-Statement für ein gesetztes Filterfeld `null`/leer, liefert die Methode `null` und die Belegart wird komplett aus dem Suchergebnis ausgeschlossen (kein Fehler).
|
||||
Aussage: Für jede Kombination aus Belegart und Filterfeld muss die zugehörige `ReceiptSearchConfiguration`-Unterklasse explizit festlegen, ob und wie das Feld unterstützt wird; fehlt die Unterstützung, wird das dem Client nicht als Fehler, sondern als (stiller) Ausschluss der Belegart mitgeteilt.
|
||||
Ergebnis: Erweiterbare, aber je Belegart individuell steuerbare Suchunterstützung.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipt-search-architecture.md, Zeilen 156-233 (Codeauszüge `CreateSqlStatementAndParameters`, "Adding New Filter Properties") - Begründung: Direktes Codezitat des Kontrollflusses inkl. `return null`-Verhalten.
|
||||
Prüfidee: Filter setzen, der von genau einer von sieben Belegarten unterstützt wird → Ergebnis enthält ausschließlich Treffer dieser einen Belegart, keine Fehlermeldung für die anderen sechs.
|
||||
Tracelinks: SyRS-04
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-08
|
||||
Titel: Rechtebasierter Ausschluss von Belegarten in der Suche
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ReceiptSearcher, AppRightsBL)
|
||||
Vorbedingung: `configuration.ShowRight` ist für eine Belegart-Konfiguration gesetzt.
|
||||
Fakt: `if (configuration.ShowRight.HasValue && !this._appRightsBL.HasRight(user.AppUser, configuration.ShowRight.Value)) return null;` — analog existieren `OnlyOwnRight` und `OnlyOwnBranchRight` zur Einschränkung auf eigene bzw. eigene Filial-Belege.
|
||||
Aussage: Fehlt einem Benutzer das für eine Belegart konfigurierte Anzeigerecht, soll die Suche für diese Belegart keine Ergebnisse liefern (Ausschluss auf Query-Ebene, nicht nachträgliche Filterung der Ergebnisliste).
|
||||
Ergebnis: Es gelangen keine Daten unautorisierter Belegarten überhaupt erst in die SQL-Ausführung.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipt-search-architecture.md, Zeilen 176-182 (Codeauszug) - Begründung: Direktes Codezitat.
|
||||
Prüfidee: Benutzer ohne `ShowRight` für Verträge sucht mit `ReceiptKinds` leer (alle Belegarten) → Ergebnisliste enthält keine Vertragsbelege, auch wenn diese existieren.
|
||||
Tracelinks: SyRS-04, SyRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-09
|
||||
Titel: Vertragsentität mit Abrechnungs- und Kontingentfeldern
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `ReceiptContract : ReceiptBase, IReceiptContract` führt u. a. `BillingIntervalKind`, `BillingIntervalDuration`, `BillingKind`, `AutomatedBilling`, `CalculationKind`, `ContingentUsedHours`, `ContingentUsedAmount`, `ContingentBalanceUsedHours/Amount`, `IsContingentLimitBilling`, `ContingentLimitValue`, `ContingentLimitKind`, `IsMonitoring`, `MonitoringValue`, `AutomatedProlongation`.
|
||||
Aussage: Die Vertragsentität soll alle zur automatisierten, kontingentbasierten Abrechnung notwendigen Parameter als persistente Felder führen, sodass `AutomaticFacturaBL` und `ContractSpecificLogic` ohne Zusatzabfragen an anderer Stelle arbeiten können.
|
||||
Ergebnis: Ein Vertrag ist als vollständig selbstbeschreibende Entität für die automatisierte Abrechnung nutzbar.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ContractLists/ReceiptContract.cs (Felder gemäß docs/reference/receipts/contracts-backend.md, Zeilen 42-90, dort mit Verweis auf die Entity-Datei zitiert) - Begründung: Entity-Felder als durchgesetzte Datenstruktur.
|
||||
Prüfidee: Vertrag mit allen Kontingent-Feldern befüllen, Serialisierung/Deserialisierung (DTO-Mapping) auf Vollständigkeit prüfen.
|
||||
Tracelinks: SyRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-10
|
||||
Titel: AutomaticFacturaBL.Contracts als Ausführungskomponente der Vertragsabrechnung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Automatisierter Abrechnungslauf wird gestartet (zeit- oder ereignisgesteuert).
|
||||
Fakt: `AutomaticFacturaBL.Contracts` (Datei `AutomaticFacturaBL.Contracts.cs`) übernimmt automatische Rechnungserstellung je Intervall, RMM-Integration und Multi-Intervall-Unterstützung laut Entwicklerdokumentation.
|
||||
Aussage: Die Komponente `AutomaticFacturaBL.Contracts` soll fällige Verträge selektieren, je Vertrag die Rechnung inkl. RMM-Positionen (siehe SwRS-11/12) erzeugen und Kontingentsalden fortschreiben.
|
||||
Ergebnis: Zentraler, fachlich vollständiger Einstiegspunkt für automatisierte Vertragsfakturierung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md, Zeilen 275-282 und 315-332 - Begründung: Benennt Klasse und Verantwortlichkeiten unter Bezug auf den Quellcode.
|
||||
Prüfidee: Codereview/Komponententest: `AutomaticFacturaBL.Contracts.cs` auf Vorhandensein der beschriebenen Verantwortlichkeiten (Fälligkeitsselektion, RMM-Aufruf, Kontingent-Update) prüfen.
|
||||
Tracelinks: SyRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-11
|
||||
Titel: RMM-Artikel-Platzhaltererkennung in Rechnungspositionen
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Rechnung wird aus Vertrag mit RMM-Konfiguration erzeugt.
|
||||
Fakt: `var rmmItem = invoice.Items.FirstOrDefault(f => (f.RichText != null && f.RichText.IndexOf("@@RMMArtikel@@", ...) > -1) || (f.Text != null && f.Text.IndexOf("@@RMMArtikel@@", ...) > -1));` — Position mit diesem Platzhalter wird entfernt und durch die tatsächlichen RMM-Positionen ersetzt; fehlt der Platzhalter, werden die Positionen nahe dem Ende der Rechnung (Position `count-2`) eingefügt.
|
||||
Aussage: Das System soll bei Vorhandensein des Platzhaltertexts `@@RMMArtikel@@` in einer Rechnungsvorlagen-Position die RMM-Nutzungspositionen exakt an dieser Stelle einfügen, andernfalls an einer definierten Fallback-Position nahe dem Rechnungsende.
|
||||
Ergebnis: RMM-Positionen erscheinen an der vom Kunden/Vorlagen-Ersteller vorgesehenen Stelle in der Rechnung.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md, Zeilen 61-64 (Codeauszug) - Begründung: Direktes Codezitat der Erkennungslogik.
|
||||
Prüfidee: Rechnungsvorlage mit Platzhalter in Position 3 von 6 → RMM-Positionen erscheinen an Position 3; Vorlage ohne Platzhalter → RMM-Positionen erscheinen bei Position (Anzahl-2).
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-12
|
||||
Titel: RMMServiceUnavailableException als kontrollierter Abbruchmechanismus
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: `RiverConnectionBL.GetContractBillingAmounts` liefert `ResultStatus.Error`.
|
||||
Fakt: `if (rmmItem != null || rmmArticleReferences.Any()) { ...; throw new RMMServiceUnavailableException(errorMsg); } return;` — die Ausnahme wird nur geworfen, wenn tatsächlich RMM-Daten erwartet werden; andernfalls kehrt die Methode ohne Fehler zurück.
|
||||
Aussage: Die Ausnahme `RMMServiceUnavailableException` soll ausschließlich dann ausgelöst werden, wenn ein RMM-Platzhalter oder konfigurierte RMM-Artikelreferenzen vorhanden sind UND der externe Dienst nicht erreichbar ist; in allen anderen Fällen darf die Rechnungserstellung unbeeinträchtigt fortgesetzt werden.
|
||||
Ergebnis: Präzise Fehlerbehandlung ohne Falsch-Positive (keine Exception bei Verträgen ohne RMM-Bezug trotz RMM-Dienstausfall).
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md, Zeilen 76-89 - Begründung: Direktes Codezitat der bedingten Ausnahmebehandlung.
|
||||
Prüfidee: Zwei Testfälle wie in SyRS-06 beschrieben, zusätzlich Prüfung der geloggten Fehlermeldung (`_logger.Error(errorMsg)`).
|
||||
Tracelinks: SyRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-13
|
||||
Titel: ReceiptBL-Kreditlimitberechnung (Netto/Brutto, Vorversionsbereinigung)
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: `customer.CreditLimitCalculationKind` ∈ {1 (Netto), sonst Brutto}; `CreditLimitCalculationKind == 2` bedeutet keine Prüfung, `CreditLimit <= 0` ebenfalls keine Prüfung.
|
||||
Fakt: `limitUsedInReceipts[receipt.ReceiptKind] -= limitUsedInPreviousVersion;` zieht explizit den in der Vorversion des gerade gespeicherten Belegs bereits eingerechneten Betrag ab, um Doppelzählung bei Belegänderungen zu vermeiden; `limitAvailable = customer.CreditLimit - limitUsed`; Abbruchbedingung `limitUsedInThisReceipt > limitAvailable && !data.SaveAlthoughCustomerLimitExceeded && !data.IgnoreCallbacks`.
|
||||
Aussage: Die Kreditlimitberechnung soll bei jeder Belegspeicherung den durch die eigene Vorversion bereits verbrauchten Limitanteil abziehen, um zu verhindern, dass eine Änderung eines bestehenden Belegs fälschlich als zusätzlicher Verbrauch gezählt wird.
|
||||
Ergebnis: Korrekte Kreditlimit-Berechnung auch bei wiederholtem Speichern/Ändern desselben Belegs.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 8661-8690 - Begründung: Exakter, zitierter Berechnungscode.
|
||||
Prüfidee: Beleg über 500€ anlegen (Limitverbrauch 500€), danach auf 600€ ändern und erneut speichern → Limitverbrauch insgesamt 600€, nicht 1100€.
|
||||
Tracelinks: SyRS-07
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-14
|
||||
Titel: Kundenentität mit Kreditlimit-Feldern (CreditLimit, CreditLimitAvailable, CreditLimitCalculationKind)
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `Customer : CustomerOptimized` führt `Decimal CreditLimit`, `Decimal CreditLimitAvailable`, `int? CreditLimitCalculationKind`; `AccountCustomer` führt zusätzlich `LockOrderAfterDunningLevel`, `DunningStop`, `DunningStopBegin/End`, `DunningInfo`, `DunningLetterAfterDays1/2/3`.
|
||||
Aussage: Die Kunden-/Kontoentität soll sowohl Kreditlimit- als auch Mahnwesen-Parameter als eigenständige, unabhängig konfigurierbare Felder führen.
|
||||
Ergebnis: Kreditlimit- und Mahnwesenlogik können getrennt voneinander konfiguriert und ausgewertet werden.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/CustomerArea/Customer.cs, Zeilen 45-47 - Begründung: Direkte Felddefinition.
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Accounts/AccountCustomer.cs, Zeilen 25, 109-112 - Begründung: Direkte Felddefinition der Mahnwesen-Parameter.
|
||||
Prüfidee: Feldweise Persistenztest: alle genannten Felder setzen, speichern, neu laden, Werte vergleichen.
|
||||
Tracelinks: SyRS-07, SyRS-08
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-15
|
||||
Titel: Fehlende Durchsetzungsstelle für LockOrderAfterDunningLevel
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `AccountBL.cs`, Zeile 192: `customerData.LockOrderAfterDunningLevel = settings.GetInt(AppSettingsConst.CustomerAssetsLockedAfterDunningLevel);` ist der einzige im BL-Kern (`Sales/Receipts/Orders`, `Sales/Receipts/ReceiptBL.cs`, `Sales/Receipts/Invoices/Dunning/DunningBL.cs`) gefundene Bezug auf dieses Feld; eine Vergleichsoperation gegen den tatsächlichen `DunningLevel` eines Kunden zur Ableitung einer Sperre wurde nicht gefunden.
|
||||
Aussage: [HYPOTHESE] Es muss eine (im Rahmen dieser Iteration nicht lokalisierte) Komponente geben, die `LockOrderAfterDunningLevel` gegen den aktuellen `DunningLevel` prüft und bei Überschreitung die Auftragserstellung verhindert oder den Benutzer warnt — andernfalls ist das Feld aktuell wirkungslos (reine Konfiguration ohne Durchsetzung).
|
||||
Ergebnis: [HYPOTHESE] Entweder existiert eine nicht gefundene Durchsetzungsstelle (z. B. in UI-ViewModels, Reporting oder einem nicht durchsuchten Modul), oder die Regel ist im aktuellen Code nicht (mehr) implementiert.
|
||||
Belege:
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Accounts/AccountBL.cs, Zeile 192 - Begründung: Einzige gefundene Codestelle, zeigt nur Zuweisung, keine Prüfung.
|
||||
Prüfidee: Vollständige Volltextsuche über die gesamte Codebasis (auch WPF.UI-ViewModels, Reports, gespeicherte Prozeduren) nach `LockOrderAfterDunningLevel`; falls keine Durchsetzung gefunden wird, Rückfrage an Fachbereich/Produktverantwortliche.
|
||||
Tracelinks: SyRS-08
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-16
|
||||
Titel: AppRightsBL.CheckRightsFromUser — parametrisierte Sichtrus/Sichmemb-Abfrage
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: SQL: `SELECT st.Recht AS ID FROM dbo.Sichtrus st INNER JOIN dbo.Sichmemb sm ON sm.Gruppe = st.Gruppe WHERE sm.Benutzer = :UserI3D AND st.Recht IN (:RightI3Ds)`, ausgeführt über `Session.Advanced.RawSqlAccess.ExecuteQuery` mit `NamedQueryParameter`.
|
||||
Aussage: Die Methode `CheckRightsFromUser(int appUserI3D, IList<int> rightI3Ds)` soll ausschließlich die Teilmenge der übergebenen Rechte-IDs zurückgeben, die dem Benutzer über mindestens eine seiner Gruppenmitgliedschaften zugewiesen sind.
|
||||
Ergebnis: Aufrufer erhalten eine eindeutige, direkt mit `Contains()` prüfbare Liste tatsächlich vorhandener Rechte.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Zeilen 95-111 - Begründung: Vollständiger, zitierter Methodencode.
|
||||
Prüfidee: Unit-/Integrationstest mit bekannter Testdatenbank: Benutzer mit 2 von 5 angefragten Rechten → Rückgabe enthält exakt 2 IDs.
|
||||
Tracelinks: SyRS-09
|
||||
Konsolidierung: Kandidat: SwRS-08 (beide nutzen Rechteprüfung als Vorfilter, aber unterschiedliche Aufrufer/Mechanik — AppRightsBL arbeitet auf App-Usern, ReceiptSearcher auf konfigurierten ShowRight-Werten)
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-17
|
||||
Titel: UserRightsConst als zentrale, hierarchisch strukturierte Rechte-Konstantensammlung
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: Entwicklerteam, System
|
||||
Vorbedingung: -
|
||||
Fakt: `UserRightsConst.cs` (in `Centron.WebServices.Core/EntitiesWrongPlace/Administration/Rights/`) gliedert Rechte-IDs nach Fachbereich (z. B. `UserRightsConst.Sales.Customer.CustomerCommon.CREATE_CUSTOMER`, `UserRightsConst.Purchase.StockList.BOOK_ARTICLE_STOCK_INTO_NEGATIVE`); neue Rechte werden per `ScriptHelpers.AddRightIfNotExists(...)` in der Tabelle `Sichrech` angelegt.
|
||||
Aussage: Jede Rechteprüfung im Code soll ausschließlich über benannte Konstanten aus `UserRightsConst` erfolgen, niemals über hartkodierte numerische IDs, um Refactoring-Sicherheit und Lesbarkeit zu gewährleisten.
|
||||
Ergebnis: Rechte-IDs sind zentral, versioniert und mit sprechenden Namen nachvollziehbar; neue Rechte folgen einem einheitlichen Anlageprozess.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/guides/development/check-userrights.md und docs/guides/development/add-a-new-right.md - Begründung: Entwicklerrichtlinien mit konkreten Codebeispielen aus `UserRightsConst.cs`/`AccountBL.cs`.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Zeilen 99-123 - Begründung: Tatsächliche Verwendung mehrerer `UserRightsConst.Purchase.StockList.*`-Konstanten als Beleg für die durchgesetzte Konvention.
|
||||
Prüfidee: Statische Codeanalyse: Suche nach numerischen Literalen in `HasUserRight(...)`/`CheckRightsFromUser(...)`-Aufrufen als Verstoß gegen die Konvention.
|
||||
Tracelinks: SyRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-18
|
||||
Titel: PasswordManagerBL — Lizenzprüfung vor Datenzugriff
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `if (LicenseManager.Instance.HasLicense(LicenseGuids.PasswordManager) == false) return Result<...>.AsError("Sie besitzen keine Lizenz für den Passwort-Manager.", DefaultMessageCodes.LicenseNotFound);` steht als erste Anweisung in `GetPasswordManagerCustomersEmployeesRights`, vor jeglicher DB-Abfrage.
|
||||
Aussage: Alle öffentlichen Methoden von `PasswordManagerBL`, die auf Zugangsdaten oder Berechtigungen zugreifen, sollen konsistent dieselbe Lizenzprüfung als ersten Schritt durchführen.
|
||||
Ergebnis: Keine Zugangsdaten werden ohne gültige Lizenz aus der Datenbank gelesen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/PasswordManager/PasswordManagerBL.cs, Zeilen 92-96 - Begründung: Zitierter Code.
|
||||
Prüfidee: Alle öffentlichen Methoden von `PasswordManagerBL` auflisten und prüfen, ob jede davon dieselbe Lizenzprüfung am Anfang durchführt (Konsistenzprüfung, da nur eine Methode im Detail gelesen wurde — siehe Analysebericht/Lücken).
|
||||
Tracelinks: SyRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-19
|
||||
Titel: TwoFactorAuthenticationBL.ValidateAuthenticationPin — TOTP-Validierung
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: Lädt Schlüssel über `GetAppUserTwoFactorAuthKey` (Named Query `PasswordManager.GetAppUserTwoFactorAuthKey`); bei leerem Schlüssel: `Result.AsError("Ihrem Benutzer ist kein Zwei-Faktor Schlüssel in der Personalverwaltung hinterlegt!")`; sonst Validierung über `Centron.Core.GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin(key, pin)`.
|
||||
Aussage: Die Methode soll zwischen zwei Fehlerfällen unterscheiden — kein Schlüssel hinterlegt vs. falsche PIN — und jeweils eine spezifische, auf Deutsch formulierte Fehlermeldung liefern.
|
||||
Ergebnis: Anwender/Administratoren erhalten eine eindeutige Diagnose bei fehlgeschlagener 2FA.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Zeilen 43-54 - Begründung: Vollständiger Methodencode.
|
||||
Prüfidee: Drei Testfälle: kein Schlüssel hinterlegt, korrekte PIN, falsche PIN → jeweils erwartetes Result-Objekt.
|
||||
Tracelinks: SyRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-20
|
||||
Titel: LicenseManager.HasLicense/GetLicenseCount als zentrale Lizenz-API
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `bool HasLicense(Guid licenseGuid)`; `Result<int?> GetLicenseCount(Guid licenseGuid)` liefert bei fehlender Lizenz `ResultStatus.Error`, bei vorhandener aber unbegrenzter Lizenz `Data == null`, sonst die konkrete Zahl; Lizenzdaten werden über `FileLicenseCache` lokal zwischengespeichert (Klasse `LicenseManager`, Zeilen 61-68).
|
||||
Aussage: Jede Komponente, die eine Mengenbeschränkung durchsetzen will, soll `GetLicenseCount` aufrufen und zwischen den drei Fällen "keine Lizenz" (Error), "unbegrenzt" (Success, Data=null) und "begrenzt auf N" (Success, Data=N) unterscheiden.
|
||||
Ergebnis: Einheitliche, dreiwertige Lizenz-Mengenlogik im gesamten Backend.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, Zeilen 26-40 (Interface) - Begründung: Vertragsdefinition.
|
||||
- [SEKUNDÄR] docs/reference/security/licensing-system.md, Zeilen 65-101 (Codebeispiel `GetLicenseCount`) - Begründung: Zeigt korrekte Verwendung/Fallunterscheidung an konkretem Beispiel (MyDay-Import).
|
||||
Prüfidee: Drei Testfälle mit präparierten Lizenzdaten: keine Lizenz, unbegrenzte Lizenz, Lizenz mit count=3 → jeweils erwartetes Result-Verhalten.
|
||||
Tracelinks: SyRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-21
|
||||
Titel: SupplierEdiBL — lieferantenspezifische partielle Klassen
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `SupplierEdiBL` ist über sechs `partial class`-Dateien organisiert (`.AlsoCH.cs`, `.Also.cs`, `.Alltron.cs`, `.Herweck.cs`, `.Komsa.cs`, `.Opentrans.cs`), jede mit eigenen `Read{Supplier}Response/Delivery/Invoice`-Methoden; z. B. `ReadAlsoCHResponse` deserialisiert via `XmlSerializer(typeof(orderresponse))` und mappt auf `EDIOrderResponseHead`.
|
||||
Aussage: Neue Lieferantenintegrationen sollen als zusätzliche partielle Klasse mit demselben Methodennamensschema (`Read{Supplier}Response/Delivery/Invoice`) hinzugefügt werden, ohne die Kernklasse `SupplierEdiBL` strukturell zu verändern.
|
||||
Ergebnis: Erweiterbarkeit für neue Lieferantenformate ohne Risiko für bestehende Integrationen.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md, Zeilen 32-42 (Klassenhierarchie) und 135-153 (Codebeispiel ALSO CH) - Begründung: Zeigt reales Codebeispiel und Namenskonvention.
|
||||
Prüfidee: Neue Testlieferant-Integration nach Schema hinzufügen und prüfen, dass `ApplyDistriToCentron` sie ohne Änderung an bestehenden Partial-Classes korrekt dispatcht.
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-22
|
||||
Titel: EdiDataType/EDIConnectionObjectKind als Dispatch-Schlüssel
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `enum EdiDataType { OpenTrans21=1, Also=2, AlsoCH=3, Herweck=4, Komsa=5, Alltron=6, Zugferd=7 }`; `enum EDIConnectionObjectKind { Order=1, OrderResponse=2, Delivery=3, Invoice=4 }`.
|
||||
Aussage: Jede EDI-Konfiguration (`SupplierEdiConfigurations`) muss genau ein `EdiDataType` und ein `EDIConnectionObjectKind` referenzieren; die Kombination beider Werte bestimmt eindeutig, welche partielle Methode in `SupplierEdiBL` zur Verarbeitung aufgerufen wird.
|
||||
Ergebnis: Eindeutige, erweiterbare Dispatch-Tabelle ohne Mehrdeutigkeiten.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md, Zeilen 177-200 - Begründung: Enum-Definitionen aus dem Quellcode zitiert.
|
||||
Prüfidee: Für jede der 7×4 theoretisch möglichen Kombinationen dokumentieren/testen, ob sie unterstützt wird (Abgleich mit Tabelle "Document Types Supported").
|
||||
Tracelinks: SyRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-23
|
||||
Titel: ActionPriceBL — Validierung Distributor und Gültigkeitszeitraum
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Anwender speichert einen neuen/geänderten Aktionspreis.
|
||||
Fakt: Validierungsregeln laut Dokumentation: `Distributor` darf nicht leer/nur Leerzeichen sein; `EffectiveFrom` muss ≤ `EffectiveUntil` sein; Anzeigefilter in `PriceMatrixViewModel.GetPriceItemsFromArticleActionPrices()`: `EffectiveFrom.StartOfDay() <= DateTime.Now && EffectiveUntil >= DateTime.Now`.
|
||||
Aussage: `ActionPriceBL.SaveOrUpdateActionPrice` soll beim Speichern beide Validierungsregeln durchsetzen und bei Verletzung den Speichervorgang mit einer Fehlermeldung abbrechen, ohne einen ungültigen Datensatz zu persistieren.
|
||||
Ergebnis: Es existieren keine Aktionspreise mit leerem Distributor oder invertiertem Gültigkeitszeitraum in der Datenbank.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/actionprice-system.md, Zeilen 301-312 - Begründung: Dokumentierte Validierungsregeln mit Verweis auf Quellklassen.
|
||||
Prüfidee: Speicherversuch mit leerem Distributor → Fehler; mit `EffectiveFrom` nach `EffectiveUntil` → Fehler; gültiger Datensatz → erfolgreich gespeichert und im Preisspiegel sichtbar bei aktuellem Datum im Bereich.
|
||||
Tracelinks: SyRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-24
|
||||
Titel: UserRightsConst.Purchase.StockList — granulares Bestandsrechte-Set
|
||||
Ebene: SwRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (ArticleBL)
|
||||
Vorbedingung: -
|
||||
Fakt: `ArticleBL` prüft im untersuchten Konstruktor-/Settings-Aufbau (Zeilen 99-123) individuell: `ID` (Modulzugriff StockList), `STORE_ARTICLE`, `CREATE_NEW_ARTICLE`, `CHANGE_ARTICLE_PRICE`, `CHANGE_SERIALNUMBER_REQUIRED_FLAG`, `RIGHT_ARTIKELVERFOLGUNG`, `BOOK_TO_STOCK` (→ `HasUserBookAdditionalStockRight`), `BOOK_FROM_STOCK` (→ `HasUserReduceStockRight`), `TRANSFER_STOCK` (→ `HasUserStockTransferRight`), `BOOK_ARTICLE_STOCK_INTO_NEGATIVE`, `CHANGE_ARTICLE_TEXT_IN_ASSET`, `CHANGE_EXTERNAL_MANUFACTURER_TEXT`, `SerialAdministration.ID`.
|
||||
Aussage: Jede der elf genannten Bestandsoperationen soll unabhängig voneinander über ein eigenes `UserRightsConst.Purchase.StockList`-Recht freigeschaltet werden können; die Ergebnisse werden in einem Settings-Objekt als bool-Flags an aufrufende Schichten (UI) weitergereicht.
|
||||
Ergebnis: Feingranulare, UI-unabhängig durchsetzbare Rechtetrennung im Lagerbereich.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Zeilen 99-123 - Begründung: Vollständige, zitierte Rechteprüfungsliste.
|
||||
Prüfidee: Für jedes der 11 Rechte einzeln: Benutzer ohne dieses (aber mit allen anderen) Recht → nur das zugehörige Flag ist `false`.
|
||||
Tracelinks: SyRS-15
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-25
|
||||
Titel: InvoiceZugferdBL — Betragstoleranzprüfung (±3,00)
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Rechnung/Gutschrift wird als ZUGFeRD/XRechnung exportiert.
|
||||
Fakt: Laut Dokumentation validiert das System, dass die Summe der Positions-Nettobeträge dem Kopf-Nettobetrag entspricht und ebenso für Bruttobeträge, mit einer Toleranz von ±3,00; innerhalb der Toleranz wird eine Warnung geloggt und der Wert korrigiert, außerhalb bricht der Export mit Fehler ab (Code-Referenz: `InvoiceZugferdBL.cs:117-158`, `:237-434`).
|
||||
Aussage: Der Export-Algorithmus soll bei einer Abweichung > 3,00 zwischen Kopf- und Positionssumme (netto oder brutto) den Export mit einem Fehler abbrechen und bei einer Abweichung ≤ 3,00 den Kopfbetrag automatisch auf die Positionssumme korrigieren und eine Warnung protokollieren.
|
||||
Ergebnis: Keine E-Rechnung mit grob inkonsistenten Beträgen verlässt das System; kleine Rundungsdifferenzen werden automatisch bereinigt.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/zugferd-field-mapping.md, Zeilen 218-221 - Begründung: Dokumentierte Regel mit konkretem Toleranzwert und Verweis auf Quellcodezeilen.
|
||||
Prüfidee: Drei Testfälle: Abweichung 0,00 (kein Hinweis), 2,50 (Warnung + Korrektur), 5,00 (Fehler, kein Export).
|
||||
Tracelinks: SyRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-26
|
||||
Titel: Steuerkategorie-Ableitung (S/E/K/G/AE) in InvoiceZugferdBL
|
||||
Ebene: SwRS
|
||||
Typ: Daten
|
||||
Akteur: System
|
||||
Vorbedingung: Rechnungsposition mit Steuersatz, Länderkennzeichen und ggf. Reverse-Charge-Flag liegt vor.
|
||||
Fakt: Zuordnung laut Dokumentation: `S` = Standard-MwSt.; `E` = steuerfrei Inland; `K` = innergemeinschaftliche Lieferung (0 %); `G` = Export außerhalb EU (0 %); `AE` = Reverse Charge (`IsReverseCharge = true`), jeweils mit vordefiniertem deutschem Hinweistext (z. B. "Steuerschuldnerschaft des Leistungsempfängers gem. §13B Abs 2 Nr. 10 UStG.").
|
||||
Aussage: Die Methode `GetTaxCategoryCode`/`GetTaxExemptionReason` soll anhand von Steuersatz, `IsReverseCharge`, `IsInlandTrade` und `IsEUTrade` genau eine der fünf Kategorien ableiten und den zugehörigen, exakt vorgegebenen deutschen Hinweistext ausgeben.
|
||||
Ergebnis: Steuerlich korrekt kategorisierte E-Rechnungspositionen gemäß EN16931/XRechnung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/zugferd-field-mapping.md, Zeilen 170-184, mit Codezeilenverweis `InvoiceZugferdBL.cs:1369-1400` - Begründung: Dokumentierte Ableitungsregeln mit exaktem Hinweistext-Wortlaut.
|
||||
Prüfidee: Je einen Testfall pro Kategorie (Standard, steuerfrei Inland, innergemeinschaftlich, Export, Reverse Charge) mit erwartetem Code und Hinweistext abgleichen.
|
||||
Tracelinks: SyRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-27
|
||||
Titel: DeveloperSecurity.Email.ValidateAddress — Implementierungsdetail
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: -
|
||||
Fakt: `AllowSendingEmailToExternalAddresses` wird bei Klasseninitialisierung einmalig aus `DebugHelper.IsReleaseBuild()` gesetzt (kein Laufzeit-Umschalten über Konfiguration); `ValidateAddress` prüft zuerst dieses Flag, dann Leerstring, dann `EndsWith(InternalEmailAddressDomain, InvariantCultureIgnoreCase)`.
|
||||
Aussage: Die Prüfreihenfolge in `ValidateAddress` soll leere/Whitespace-Adressen unverändert durchreichen (kein Ersatz, kein Fehler) und Groß-/Kleinschreibung der Domain ignorieren.
|
||||
Ergebnis: Robuste Adressvalidierung ohne Nebenwirkungen bei leeren Eingaben oder Schreibweise-Varianten der internen Domain.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Common/DeveloperSecurity.cs, Zeilen 30-46 - Begründung: Vollständiger, zitierter Methodencode.
|
||||
Prüfidee: Randfalltests: leere Adresse, Adresse "NEXOWARE.COM"-Großschreibung, Adresse ohne @-Zeichen.
|
||||
Tracelinks: SyRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SwRS-28
|
||||
Titel: ILogic/BLLogic/WSLogic-Namenskonvention und ClassContainer-Registrierung
|
||||
Ebene: SwRS
|
||||
Typ: funktional
|
||||
Akteur: Entwicklerteam, System (ClassContainer)
|
||||
Vorbedingung: -
|
||||
Fakt: Namenskonvention `I{Module}Logic`, `BL{Module}Logic`, `WS{Module}Logic`; laut Dokumentation registriert sich bei Einhaltung der Konvention die passende Implementierung automatisch beim `ClassContainer`; `AppModuleController.SupportsConnectionTypes` legt je Modul fest, welche Verbindungstypen (SqlServer, CentronWebServices) unterstützt werden.
|
||||
Aussage: Jedes Modul, das diese Namenskonvention nicht einhält, kann nicht automatisch über `ClassContainer` aufgelöst werden und erfordert manuelle Registrierung — Abweichungen sind ein Wartbarkeitsrisiko.
|
||||
Ergebnis: Konsistente, automatisch auflösbare Modul-Registrierung bei Konventionstreue.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md, Zeilen 17-95 - Begründung: Dokumentierte Konvention mit Codebeispiel.
|
||||
Prüfidee: Codebase-weite Suche nach Interfaces mit Suffix `Logic`, die NICHT dem Muster `I*Logic`/`BL*Logic`/`WS*Logic` folgen, als Qualitätsindikator für Konventionsabweichungen (siehe Konsolidierungshinweis Analysebericht).
|
||||
Tracelinks: SyRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+370
@@ -0,0 +1,370 @@
|
||||
# System Requirements Specification (SyRS) — c-entron ERP
|
||||
|
||||
Ebene gemäß ISO/IEC/IEEE 29148:2018: Systemverhalten, Schnittstellen, Performance- und Sicherheitsanforderungen. Jede Anforderung konkretisiert eine StRS-Anforderung auf Systemebene und wird in der SwRS auf Komponentenebene weiter verfeinert.
|
||||
|
||||
Nicht-funktionale Anforderungen sind zusätzlich mit ihrem **ISO/IEC 25010**-Qualitätsmerkmal gekennzeichnet.
|
||||
|
||||
---
|
||||
|
||||
```
|
||||
ID: SyRS-01
|
||||
Titel: Gemeinsames Belegdatenmodell (Kopf/Position) je Belegart
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (Persistenzschicht)
|
||||
Vorbedingung: Eine der sieben Belegarten wird angelegt oder geladen.
|
||||
Fakt: `ReceiptBase` definiert 20+ gemeinsame virtuelle Properties (Number, Date, Version, State, BranchI3D, CurrencyI3D, Receiver, AddressI3D, CreatedByI3D/ChangedByI3D, ConcurrencyControlGuid) sowie vier abstrakte Item-Methoden (`GetReceiptItems`, `SetReceiptItems`, `AddItem`, `RemoveItem`), die jede konkrete Belegart (`ReceiptOffer`, `ReceiptOrder`, `ReceiptInvoice`, `ReceiptContract`, ...) implementieren muss.
|
||||
Aussage: Das System soll für jede Belegart ein Kopf-Objekt bereitstellen, das mindestens die in `ReceiptBase` definierten Felder führt und über eine polymorphe Schnittstelle (`IReceiptBase`) einheitlich behandelt werden kann, unabhängig von der konkreten Belegart.
|
||||
Ergebnis: Generischer Code (z. B. `ReceiptBL.GetReceiptByI3D<T>`, `SaveReceipt<T>`) kann alle Belegarten ohne typspezifische Sonderbehandlung verarbeiten.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Entities/Entities/Sales/Receipts/ReceiptBase.cs, Zeilen 9-72 - Begründung: Vollständige, im Code durchgesetzte gemeinsame Struktur und Vertrag (abstract/virtual Members).
|
||||
Prüfidee: Für alle sieben Belegarten per Reflection prüfen, dass sie von `ReceiptBase` erben und keine der Basiseigenschaften "shadowen"/überschreiben.
|
||||
Tracelinks: StRS-01
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-02
|
||||
Titel: Belegstatusmaschine mit Sperrverhalten für stornierte Belege
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Ein Beleg mit Status `Active` oder `Completed` existiert.
|
||||
Fakt: `ReceiptState` kennt genau drei Werte; `ReceiptBL` (Zeilen 4936-4951) verweigert das Setzen von Bezahlt-Status bei `State == Canceled` mit definierter Fehlermeldung, setzt aber bei `isPaid` zwischen `Active` und `Completed` um; ein Zustandsübergang nach `Canceled` selbst sowie Übergänge zurück aus `Completed`/`Canceled` wurden im untersuchten Code-Ausschnitt nicht vollständig nachverfolgt.
|
||||
Aussage: Das System soll den Zustand eines Belegs strikt auf die drei Werte Active/Completed/Canceled begrenzen und für Belege im Zustand `Canceled` jede Änderung des Zahlungsstatus verhindern.
|
||||
Ergebnis: Ein stornierter Beleg kann nicht nachträglich als (un)bezahlt markiert werden; die Statusänderung Active↔Completed erfolgt ausschließlich über `isPaid`.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Interfaces/Sales/Receipts/ReceiptState.cs - Begründung: Enum als einzige gültige Werteliste.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 4936-4951 - Begründung: Durchgesetzte Zustandsübergangslogik mit Sperrbedingung.
|
||||
Prüfidee: Automatisierter Test: Beleg canceln, `SetPaid(true)` aufrufen → Fehler; Beleg mit State=Active, `SetPaid(true)` → State wird Completed und Log-Eintrag `CreateSetAsPaidEntry` wird erzeugt.
|
||||
Tracelinks: StRS-02
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-03
|
||||
Titel: Versionierungsmechanismus mit 1:1-Schattentabellen
|
||||
Ebene: SyRS
|
||||
Typ: Daten
|
||||
Akteur: System (AssetHeadDAO)
|
||||
Vorbedingung: Ein Beleg (Kopf und/oder Positionen) wird gespeichert.
|
||||
Fakt: Für jede *Kopf/*Pos-Tabelle existiert eine *KopfVersions/*PosVersions-Tabelle mit identischem Spaltensatz plus `OriginalI3D` (und für Positionen zusätzlich `KopfVersionsI3D`); `AssetHeadDAO.SaveAssetVersion` kopiert per INSERT...SELECT den aktuellen Datensatz in die Versionstabelle, bevor er verändert wird.
|
||||
Aussage: Das System soll bei jeder speichernden Änderung eines Belegs den vorherigen vollständigen Datensatz (Kopf und zugehörige Positionen) in eine strukturgleiche Versionstabelle kopieren, bevor die Änderung angewendet wird.
|
||||
Ergebnis: Zu jedem historischen Zeitpunkt kann der exakte Belegzustand aus den Versionstabellen rekonstruiert werden.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/receipts-backend-architecture.md, Zeilen 145-204 (inkl. SQL-Beispiel) - Begründung: Beschreibt den durch `AssetHeadDAO.SaveAssetVersion` durchgesetzten Kopiervorgang mit konkretem SQL.
|
||||
- [KONTEXT] docs/reference/receipts/contracts-backend.md, Zeilen 162-181 - Begründung: Bestätigt dasselbe Muster für Vertragsdaten als weiteres Beispiel.
|
||||
Prüfidee: Schema-Diff zwischen `AngKopf` und `AngKopfVersions` (bzw. `VertragPos`/`VertragPosVersions`) automatisiert prüfen: alle Spalten aus der Basistabelle (außer I3D) müssen 1:1 in der Versionstabelle vorhanden sein.
|
||||
Tracelinks: StRS-03
|
||||
Konsolidierung: nein
|
||||
Status: belegt; Workaround (Altsystem-Musterlösung statt generischem Temporal-Table-Feature der Datenbank)
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-04
|
||||
Titel: Konfigurationsgetriebene, rechtebeschränkte Multi-Belegart-Suche
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: REST-Client (WPF-UI, Web), System
|
||||
Vorbedingung: Anwender ist angemeldet, `ReceiptSearchFilter` ist befüllt.
|
||||
Fakt: `ReceiptSearcher.SearchReceipts` iteriert über alle registrierten `ReceiptSearchConfiguration`-Klassen, überspringt Belegarten ohne passendes WHERE-Statement für einen gesetzten Filter, prüft `configuration.ShowRight` gegen die Benutzerrechte und führt rohes SQL mit 5-Minuten-Timeout aus; Ergebnisse werden nach ObjectKind, dann Nummer absteigend sortiert.
|
||||
Aussage: Das System soll über eine REST-Schnittstelle (`SearchReceiptsThroughPaging`) eine paginierte, über alle Belegarten aggregierte Suche anbieten, die nicht-unterstützte Filter je Belegart erkennt, fehlende Anzeigerechte durch Auslassen der jeweiligen Belegart durchsetzt und Suchanfragen nach spätestens 5 Minuten abbricht.
|
||||
Ergebnis: Client erhält eine einzige paginierte Trefferliste über alle für ihn sichtbaren Belegarten; nicht unterstützte Filterkombinationen führen zu keinem Fehler, sondern zum Ausschluss der betroffenen Belegart.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipt-search-architecture.md, Codeauszug Zeilen 74-99 (`ReceiptSearcher.SearchReceipts`) und Zeilen 176-190 (Rechteprüfung/Aktiv-Filter) - Begründung: Direktes Codezitat aus `ReceiptSearcher.cs`.
|
||||
Prüfidee: Lasttest: Suche über alle sieben Belegarten mit großem Datenbestand (>100.000 Belege je Art) ausführen, Antwortzeit und Einhaltung des 5-Minuten-Timeouts messen.
|
||||
Tracelinks: StRS-04
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-05
|
||||
Titel: Konfigurierbares Abrechnungsintervall für Verträge
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (AutomaticFacturaBL)
|
||||
Vorbedingung: Vertrag mit `AutomatedBilling = true` existiert.
|
||||
Fakt: `ReceiptContract` führt `BillingIntervalKind` (Daily/Monthly/Quarterly/Yearly), `BillingIntervalDuration` (z. B. 3 für vierteljährlich bei Kind=Monthly) und `LastSubsequentBillingDate`; `AutomaticFacturaBL.Contracts` wertet diese zur Fälligkeitsermittlung aus.
|
||||
Aussage: Das System soll für jeden Vertrag anhand von Intervallart und -dauer den nächsten Fälligkeitstermin berechnen und bei Fälligkeit automatisiert eine Rechnung erzeugen, sofern `AutomatedBilling` aktiv ist.
|
||||
Ergebnis: Verträge werden termingerecht abgerechnet, ohne dass ein Mitarbeiter den Termin manuell überwachen muss.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/contracts-backend.md, Zeilen 42-48 (Feldbeschreibung) und Zeilen 315-332 (Ablaufbeschreibung "Automated Billing Process") - Begründung: Dokumentiert Felder und Ablauf unter Verweis auf `AutomaticFacturaBL`.
|
||||
Prüfidee: Verträge mit unterschiedlichen Intervallkombinationen (z. B. Monthly/1, Monthly/3, Yearly/1) anlegen und den automatisierten Lauf für verschiedene Stichtage simulieren; erwartete Rechnungstermine mit tatsächlich erzeugten vergleichen.
|
||||
Tracelinks: StRS-05
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-06
|
||||
Titel: Harter Abbruch der Rechnungserstellung bei RMM-Dienstausfall
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System, externer RMM-Dienst
|
||||
Vorbedingung: Vertrag erfordert RMM-Daten (`WhetherRMM=true` oder RMM-Artikelreferenzen vorhanden) und die Rechnungserstellung für den Vertrag läuft.
|
||||
Fakt: `RiverConnectionBL.GetContractBillingAmounts` liefert bei Nichterreichbarkeit `ResultStatus.Error`; nur wenn zugleich ein RMM-Platzhalter oder RMM-Artikelreferenzen vorhanden sind, wird `RMMServiceUnavailableException` geworfen, andernfalls wird der RMM-Schritt stillschweigend übersprungen (`return;`).
|
||||
Aussage: Das System soll die automatisierte Rechnungserstellung für einen Vertrag abbrechen (Exception), wenn RMM-Nutzungsdaten erwartet werden, der externe RMM-Dienst aber nicht erreichbar ist; sind keine RMM-Daten für den Vertrag erforderlich, soll die Rechnungserstellung unbeeinflusst fortgesetzt werden.
|
||||
Ergebnis: Es werden keine Rechnungen mit fehlenden, aber vertraglich vereinbarten Nutzungsdaten erzeugt.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/Contract-Billing-RMM-Article-Logic.md, Zeilen 76-89 (Codeauszug mit `if (riverbirdStatisticsResult.Status is ResultStatus.Error)` und `throw new RMMServiceUnavailableException`) - Begründung: Direktes Codezitat, zeigt bedingte Ausnahmebehandlung exakt.
|
||||
Prüfidee: Integrationstest mit simuliertem RMM-Dienstausfall: (a) Vertrag mit RMM-Artikelreferenzen → Exception und Log-Eintrag; (b) Vertrag ohne RMM-Bezug → Rechnung wird trotz RMM-Ausfall normal erstellt.
|
||||
Tracelinks: StRS-06
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-07
|
||||
Titel: Kreditlimitberechnung über alle limitrelevanten Belegarten mit Override
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (ReceiptBL)
|
||||
Vorbedingung: Kunde hat `CreditLimitCalculationKind` (1=Netto, 2=Brutto-Ausnahme=keine Prüfung) gesetzt und `CreditLimit > 0`.
|
||||
Fakt: `ReceiptBL` summiert über `SpecificLogics.All()` je Belegart den durch `TakesPlaceInLimitCalculation` markierten, bereits verbrauchten Limitanteil (`GetUsedLimitAmount`), zieht den in der Vorversion des aktuellen Belegs verbrauchten Anteil ab, vergleicht die Summe mit `customer.CreditLimit` und schreibt das Ergebnis nach `customer.CreditLimitAvailable`. Bei Überschreitung wird nur dann gespeichert, wenn `data.SaveAlthoughCustomerLimitExceeded == true` oder `data.IgnoreCallbacks == true`.
|
||||
Aussage: Das System soll das Kreditlimit eines Kunden fortlaufend aus der Summe aller offenen, limitrelevanten Belege (abzüglich der Vorversion des gerade gespeicherten Belegs) berechnen, den verfügbaren Restbetrag persistieren und eine Überschreitung nur nach expliziter Anwenderbestätigung zulassen.
|
||||
Ergebnis: `CreditLimitAvailable` ist nach jedem Speichervorgang aktuell; Überschreitungen ohne Bestätigung werden verhindert.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Sales/Receipts/ReceiptBL.cs, Zeilen 8646-8777 - Begründung: Vollständige Berechnungs- und Abbruchlogik im Code, inkl. Netto-/Brutto-Unterscheidung und Vorversions-Bereinigung.
|
||||
Prüfidee: Regressionstest mit mehrstufiger Belegkette (Angebot→Auftrag→Rechnung), bei dem derselbe Betrag nicht doppelt ins Limit einfließt (Prüfung `GetLimitUsedInOriginReceipts`-Abzug).
|
||||
Tracelinks: StRS-07
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-08
|
||||
Titel: Auftragssperre bei Erreichen einer konfigurierten Mahnstufe
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System
|
||||
Vorbedingung: Kundenkonto hat eine Mahnstufe erreicht.
|
||||
Fakt: Lediglich die Initialisierung des Felds `AccountCustomer.LockOrderAfterDunningLevel` aus einer globalen Einstellung wurde gefunden (`AccountBL.cs`, Zeile 192); eine Auswertung dieses Felds zur tatsächlichen Sperrung eines neuen Auftrags wurde in `ReceiptBL.cs`/`OrderSpecificLogic.cs`/`DunningBL.cs` nicht gefunden.
|
||||
Aussage: [HYPOTHESE] Das System soll beim Anlegen eines neuen Auftrags (und ggf. weiterer Belegarten) prüfen, ob die aktuelle Mahnstufe des Kunden `LockOrderAfterDunningLevel` erreicht oder überschreitet, und die Erstellung in diesem Fall verweigern oder eine Warnung anzeigen.
|
||||
Ergebnis: [HYPOTHESE] Kunden oberhalb der konfigurierten Mahnstufe können keine neuen Aufträge auslösen.
|
||||
Belege:
|
||||
- [SEKUNDÄR] src/backend/Centron.BL/Accounts/AccountBL.cs, Zeile 192 - Begründung: Zeigt nur Initialisierung, keine Durchsetzung.
|
||||
Prüfidee: Gezielte Codesuche nach lesendem Zugriff auf `LockOrderAfterDunningLevel` außerhalb von Zuweisung/Mapping; Rückfrage an Fachbereich, ob die Sperre ausschließlich manuell (Mitarbeiterhinweis) erfolgt.
|
||||
Tracelinks: StRS-08
|
||||
Konsolidierung: nein
|
||||
Status: HYPOTHESE
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-09
|
||||
Titel: Zentrale, gruppenbasierte Rechteprüfung als Systemdienst
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Alle Systemschichten (BL, Webservice, UI)
|
||||
Vorbedingung: Eine sicherheitsrelevante Operation wird angefragt.
|
||||
Fakt: `AppRightsBL.CheckRightsFromUser(appUserI3D, rightI3Ds)` führt einen parametrisierten Join über `Sichtrus` (Recht↔Gruppe) und `Sichmemb` (Benutzer↔Gruppe) aus und liefert die Teilmenge der angefragten Rechte zurück, die der Benutzer tatsächlich besitzt; `CheckWebRightsFromUser` bildet dasselbe Muster für Web-Accounts über `WebAccountsRights` ab.
|
||||
Aussage: Das System soll für jede sicherheitsrelevante Operation eine zentrale, konsistente Prüf-API bereitstellen, die anhand der Gruppenmitgliedschaften eines Benutzers (App-Benutzer wie auch Web-Account) ermittelt, welche der angefragten Rechte tatsächlich zustehen.
|
||||
Ergebnis: Rechteprüfungen erfolgen einheitlich über eine einzige, zentrale Komponente statt verstreuter Ad-hoc-Prüfungen.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Zeilen 95-135 - Begründung: Zentrale, parametrisierte SQL-Implementierung, die von allen BL-Klassen (u. a. `AccountBL`, `ReceiptSearcher`) wiederverwendet wird.
|
||||
Prüfidee: Benutzer mit 3 angefragten Rechten, von denen er nur 1 besitzt, aufrufen → Rückgabemenge enthält exakt dieses eine Recht.
|
||||
Tracelinks: StRS-09
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-10
|
||||
Titel: Lizenzpflicht für Passwort-Manager-Zugriff
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: System (PasswordManagerBL)
|
||||
Vorbedingung: Ein Client fragt Zugangsdaten-Rechte über `GetPasswordManagerCustomersEmployeesRights` ab.
|
||||
Fakt: Die Methode prüft als erste Aktion `LicenseManager.Instance.HasLicense(LicenseGuids.PasswordManager)` und liefert bei fehlender Lizenz `Result.AsError(..., DefaultMessageCodes.LicenseNotFound)`, bevor irgendeine Datenbankabfrage erfolgt.
|
||||
Aussage: Das System soll den Zugriff auf Passwort-Manager-Funktionen serverseitig (nicht nur UI-seitig) an eine gültige Lizenz binden.
|
||||
Ergebnis: Ohne Lizenz wird kein Datenzugriff durchgeführt, unabhängig davon, ob ein Client die UI-Sperre umgeht.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/PasswordManager/PasswordManagerBL.cs, Zeilen 92-96 - Begründung: Serverseitige, vor Datenzugriff platzierte Lizenzprüfung.
|
||||
Prüfidee: Direkter Webservice-Aufruf ohne UI (z. B. via Testclient) gegen einen Kunden ohne Passwort-Manager-Lizenz → Fehlerantwort mit `LicenseNotFound`, keine Daten im Response-Body.
|
||||
Tracelinks: StRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-11
|
||||
Titel: TOTP-basierte Zwei-Faktor-Authentifizierung
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Mitarbeiter, System
|
||||
Vorbedingung: Für den Mitarbeiter ist ein 2FA-Schlüssel hinterlegt (`AppUserTwoFactorAuthKeyExists = true`).
|
||||
Fakt: `TwoFactorAuthenticationBL.ValidateAuthenticationPin` lädt den hinterlegten Schlüssel und validiert die eingegebene PIN über `Centron.Core.GoogleAuthenticator.TwoFactorAuthenticator.ValidatePin` (TOTP-Standardalgorithmus); ohne hinterlegten Schlüssel wird ein spezifischer Fehler zurückgegeben statt eine PIN-Prüfung zu versuchen.
|
||||
Aussage: Das System soll, wenn für einen Benutzer ein Zwei-Faktor-Schlüssel hinterlegt ist, bei der Authentifizierung zusätzlich zur Passwortprüfung eine zeitbasierte Einmal-PIN (TOTP) verlangen und nur bei Übereinstimmung den Zugriff gewähren.
|
||||
Ergebnis: Konten mit hinterlegtem 2FA-Schlüssel sind zusätzlich zum Passwort durch eine zeitlich begrenzte PIN geschützt.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/TwoFactorAuthenticator/TwoFactorAuthenticationBL.cs, Zeilen 43-54 - Begründung: Vollständige Prüf-Implementierung inkl. Fehlerfällen.
|
||||
Prüfidee: PIN-Test mit korrektem TOTP-Wert (aus demselben Secret berechnet) → Erfolg; mit falschem/abgelaufenem Wert → "Die eingegebene PIN ist ungültig!"; Benutzer ohne Schlüssel → spezifischer Hinweistext.
|
||||
Tracelinks: StRS-10
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-12
|
||||
Titel: GUID-basiertes Lizenzmodell mit Zähler, Ablaufdatum und Ablaufversion
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (LicenseManager), Lizenzserver (extern)
|
||||
Vorbedingung: Lizenzdatei/-server ist erreichbar bzw. lokal gecacht (`FileLicenseCache`).
|
||||
Fakt: `ILicenseManager` definiert `HasLicense(Guid)`, `GetLicenseCount(Guid) : Result<int?>` (null = unbegrenzt) und `CheckLicense(ApplicationKind, version, user) : Result<Guid>`; Lizenzdaten werden vom externen Lizenzserver bezogen und lokal gecacht.
|
||||
Aussage: Das System soll für jede Lizenz-GUID unabhängig prüfen können, ob sie vorhanden ist, welche Nutzungsmenge sie erlaubt (endlich oder unbegrenzt) und ob sie für die aktuelle Anwendungsversion noch gültig ist, wobei diese Information aus einem zentralen Lizenzserver bezogen und lokal zwischengespeichert wird.
|
||||
Ergebnis: Feature- und Mengenbeschränkungen sind zentral und konsistent für alle c-entron-Komponenten (Desktop, Webservice) durchsetzbar, auch bei temporärem Verbindungsausfall zum Lizenzserver (Cache).
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Licensing/LicenseManager.cs, Zeilen 26-68 - Begründung: Interface-Vertrag und tatsächliche Cache-/Proxy-Konfiguration im Code.
|
||||
Prüfidee: Lizenzserver offline simulieren → `HasLicense` liefert weiterhin Werte aus `FileLicenseCache`; Lizenz mit `count=3` grenzt eine vierte Nutzung ab (siehe Beispiel MyDay-Import in Dokumentation).
|
||||
Tracelinks: StRS-11
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-13
|
||||
Titel: Formatspezifisches EDI-Parsing mit einheitlichem Dispatch
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (SupplierEdiBL), externe Distributoren
|
||||
Vorbedingung: EDI-Datei liegt im konfigurierten FTP/SFTP-Verzeichnis vor.
|
||||
Fakt: `ApplyDistriToCentron(List<EDIDistriFile>, SupplierEdiConfigurations, OrderInfo)` routet anhand `EdiDataType` (OpenTrans21, Also, AlsoCH, Herweck, Komsa, Alltron, Zugferd) und `EDIConnectionObjectKind` (Order, OrderResponse, Delivery, Invoice) an lieferantenspezifische partielle Klassen; nicht jede Kombination wird unterstützt (z. B. Komsa ohne Invoice-Integration).
|
||||
Aussage: Das System soll eingehende EDI-Dateien anhand von Format und Dokumenttyp eindeutig einer lieferantenspezifischen Verarbeitungsroutine zuordnen und nach erfolgreicher Verarbeitung die Quelldatei bereinigen.
|
||||
Ergebnis: Jede unterstützte Lieferant/Format/Dokumenttyp-Kombination wird korrekt verarbeitet; nicht unterstützte Kombinationen werden nicht stillschweigend ignoriert, sondern erzeugen einen definierten Log-/Fehlerzustand (`EDILogState`).
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/edi/edi-architecture.md, Zeilen 91-106 (Methodensignatur und Verantwortlichkeiten) und Tabelle Zeilen 110-123 (unterstützte Kombinationen) - Begründung: Dokumentiert Dispatch-Mechanismus mit Bezug auf tatsächliche Methode und Klassenhierarchie.
|
||||
Prüfidee: Für jede in der Tabelle als "✗" markierte Kombination (z. B. Komsa+Invoice) prüfen, dass das System dies erkennt und keinen Verarbeitungsversuch unternimmt, statt eine Ausnahme unbehandelt zu werfen.
|
||||
Tracelinks: StRS-12
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-14
|
||||
Titel: Datumsbasierte Sichtbarkeitsfilterung von Aktionspreisen
|
||||
Ebene: SyRS
|
||||
Typ: funktional
|
||||
Akteur: System (PriceMatrixViewModel)
|
||||
Vorbedingung: Preisspiegel für einen Artikel wird geladen.
|
||||
Fakt: `GetPriceItemsFromArticleActionPrices()` filtert Aktionspreise mit `EffectiveFrom.StartOfDay() <= DateTime.Now && EffectiveUntil >= DateTime.Now`; `ActionPriceBL` erzwingt beim Speichern `Distributor` als Pflichtfeld und `EffectiveFrom ≤ EffectiveUntil`.
|
||||
Aussage: Das System soll beim Speichern eines Aktionspreises einen nicht-leeren Distributor und eine gültige Datumsreihenfolge erzwingen und beim Anzeigen im Preisspiegel ausschließlich aktuell gültige Aktionspreise berücksichtigen.
|
||||
Ergebnis: Fehlerhafte oder abgelaufene Aktionspreise gelangen nicht in die Preisfindung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/receipts/actionprice-system.md, Zeilen 195-198 und 301-312 - Begründung: Dokumentiert Filterausdruck und Validierungsregeln mit Verweis auf `PriceMatrixViewModel.cs` (Zeilen 416-459) als Quelle.
|
||||
Prüfidee: Aktionspreis mit `EffectiveFrom > EffectiveUntil` speichern → Validierungsfehler; Aktionspreis mit `EffectiveUntil = gestern` → wird im Preisspiegel nicht angezeigt.
|
||||
Tracelinks: StRS-13
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-15
|
||||
Titel: Granulare Rechteprüfung je Bestandsoperation
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit
|
||||
Akteur: Lagermitarbeiter, System (ArticleBL)
|
||||
Vorbedingung: Benutzer öffnet Bestandsfunktionen eines Artikels.
|
||||
Fakt: `ArticleBL` liest für den aktuellen Benutzer separat die Rechte `STORE_ARTICLE`, `CREATE_NEW_ARTICLE`, `CHANGE_ARTICLE_PRICE`, `CHANGE_SERIALNUMBER_REQUIRED_FLAG`, `RIGHT_ARTIKELVERFOLGUNG`, `BOOK_TO_STOCK`, `BOOK_FROM_STOCK`, `TRANSFER_STOCK`, `BOOK_ARTICLE_STOCK_INTO_NEGATIVE`, `CHANGE_ARTICLE_TEXT_IN_ASSET`, `CHANGE_EXTERNAL_MANUFACTURER_TEXT` und setzt daraus feingranulare Settings-Flags (`HasUserBookAdditionalStockRight` usw.).
|
||||
Aussage: Das System soll jede einzelne Bestandsoperation (Zubuchen, Abbuchen, Umlagern, Negativbuchung, Preisänderung, Artikeltext ändern) unabhängig voneinander gegen ein eigenes Benutzerrecht prüfen und dem Client die jeweils zulässigen Operationen als Flags mitteilen.
|
||||
Ergebnis: Die UI kann nicht erlaubte Bestandsfunktionen ausblenden/deaktivieren; das Backend verweigert nicht erlaubte Operationen unabhängig vom UI-Zustand.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.BL/Warehousing/ArticleBL.cs, Zeilen 99-123 - Begründung: Direkte, vollständige Auflistung der geprüften Rechte im Code.
|
||||
Prüfidee: Für jedes der 10 Rechte einen Benutzer ohne dieses Recht testen und sicherstellen, dass das zugehörige Flag `false` ist und die serverseitige Aktion verweigert wird (nicht nur UI-Ausblendung).
|
||||
Tracelinks: StRS-14
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-16
|
||||
Titel: Normkonforme E-Rechnungsgenerierung mit Betragsvalidierung
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle
|
||||
Akteur: System (InvoiceZugferdBL)
|
||||
Vorbedingung: Rechnung/Gutschrift ist vollständig und final.
|
||||
Fakt: `InvoiceZugferdBL` unterstützt ZUGFeRD 1.0/2.0/2.1 und XRechnung 1.2/2.0/2.2/2.3.1/3.0.1; validiert Summe der Positions-Nettobeträge gegen Kopf-Nettobetrag (Toleranz ±3,00, darüber Fehler/Abbruch, darunter Warnung mit Korrektur) und leitet die Steuerkategorie (S/E/K/G/AE) aus Steuersatz, Reverse-Charge-Flag und Länderkennzeichen ab.
|
||||
Aussage: Das System soll beim Export einer Rechnung/Gutschrift als ZUGFeRD/XRechnung-XML die rechnerische Konsistenz zwischen Kopf- und Positionssummen innerhalb einer Toleranz von 3,00 Währungseinheiten sicherstellen und die korrekte Steuerkategorie nach EN16931-Regeln zuweisen.
|
||||
Ergebnis: Erzeugte E-Rechnungen sind sowohl rechnerisch konsistent als auch steuerlich korrekt kategorisiert; grobe Inkonsistenzen führen zum Exportabbruch statt zu einer fehlerhaften E-Rechnung.
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/reference/zugferd-field-mapping.md, Zeilen 173-184 (Steuerkategorien) und 218-221 (Validierungstoleranzen), mit Codezeilenverweisen (`InvoiceZugferdBL.cs:1369-1400`) - Begründung: Dokumentiert konkrete, im Code verankerte Regeln mit exakten Zeilenverweisen.
|
||||
Prüfidee: E-Rechnung mit Reverse-Charge-Fall exportieren → Steuerkategorie "AE" mit Hinweistext "Steuerschuldnerschaft..."; Testfall mit absichtlicher Rundungsdifferenz von 3,50 → Export schlägt fehl.
|
||||
Tracelinks: StRS-15
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-17
|
||||
Titel: Automatische Umleitung externer E-Mail-Adressen in Nicht-Produktivbuilds
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (Sicherheit / Zuverlässigkeit, ISO 25010: Sicherheit)
|
||||
Akteur: System (DeveloperSecurity)
|
||||
Vorbedingung: Anwendung läuft als DEBUG-Build.
|
||||
Fakt: `DeveloperSecurity.Email.ValidateAddress` prüft `AllowSendingEmailToExternalAddresses` (= `DebugHelper.IsReleaseBuild()`); ist dies `false` (DEBUG) und die Zieladresse endet nicht auf `nexoware.com`, wird sie durch `test@nexoware.com` ersetzt.
|
||||
Aussage: Das System soll ausgehende E-Mails in Nicht-Produktiv-(DEBUG-)Builds automatisch auf eine interne Testadresse umleiten, sofern die ursprüngliche Zieladresse nicht zur internen Domain gehört.
|
||||
Ergebnis: Keine E-Mail aus einer Testinstanz erreicht eine tatsächliche externe (Kunden-)Adresse.
|
||||
Belege:
|
||||
- [PRIMÄR] src/backend/Centron.Common/DeveloperSecurity.cs, Zeilen 8-46 - Begründung: Vollständige Implementierung im Code.
|
||||
Prüfidee: Unit-Test: `ValidateAddress("kunde@fremd.de")` in simuliertem DEBUG-Kontext → liefert `test@nexoware.com`; `ValidateAddress("kollege@nexoware.com")` → liefert unverändert.
|
||||
Tracelinks: StRS-16
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-18
|
||||
Titel: Einheitliche Logic-Schnittstelle für Direktzugriff und Webservice-Zugriff
|
||||
Ebene: SyRS
|
||||
Typ: Schnittstelle (ISO 25010: Übertragbarkeit/Wartbarkeit)
|
||||
Akteur: Client-Anwendungen (WPF, Outlook-Add-in, Mobile), Entwicklerteam
|
||||
Vorbedingung: Ein Modul benötigt Datenzugriff.
|
||||
Fakt: Vorschrift: je Modul ein `I{Modul}Logic`-Interface, `BL{Modul}Logic` (Direktzugriff über `BLSession`/NHibernate) und `WS{Modul}Logic` (über `ICentronWebServiceConnection`); Client wählt über `AppModuleController.SupportsConnectionTypes` (SqlServer/CentronWebServices) die passende Implementierung über `ClassContainer`.
|
||||
Aussage: Das System soll für jedes fachliche Modul zwei alternative, schnittstellenkompatible Implementierungen bereitstellen — eine für direkten Datenbankzugriff, eine für Zugriff über den Webservice —, sodass ein Wechsel des Verbindungstyps keine Änderung im aufrufenden Client-Code erfordert.
|
||||
Ergebnis: Derselbe Client-Code funktioniert unverändert im LAN-Betrieb (Direktzugriff) und im Fernzugriff/Cloud-Betrieb (Webservice).
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md, Zeilen 36-95 - Begründung: Vollständige Codebeispiele für Interface/BL/WS-Trio als dokumentierte Pflichtarchitektur.
|
||||
Prüfidee: Für ein bestehendes Modul (`IAccountContractsLogic`) beide Implementierungen gegen dieselbe Testsuite laufen lassen und identisches Verhalten (bei identischen Daten) verifizieren.
|
||||
Tracelinks: StRS-17
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-19
|
||||
Titel: Parametrisierte Datenbankzugriffe bei dynamischer Filterkomposition
|
||||
Ebene: SyRS
|
||||
Typ: Sicherheit (ISO 25010: Sicherheit)
|
||||
Akteur: System
|
||||
Vorbedingung: Ein Suchfilter mit Benutzereingaben wird in eine SQL-Abfrage übersetzt.
|
||||
Fakt: `ReceiptSearcher.CreateSqlStatementAndParameters` und `AppRightsBL.CheckRightsFromUser` binden alle variablen Werte ausschließlich über `NamedQueryParameter`-Objekte ein; WHERE-Klauseln werden aus vordefinierten, statischen Konfigurationsstrings zusammengesetzt, nie aus Benutzereingaben direkt.
|
||||
Aussage: Das System soll bei jeder dynamisch zusammengesetzten SQL-Abfrage Benutzereingaben ausschließlich als parametrisierte Werte einbinden, niemals als Teil des SQL-Textes selbst.
|
||||
Ergebnis: Klassische SQL-Injection über Suchfelder oder Rechte-IDs ist ausgeschlossen.
|
||||
Belege:
|
||||
- [PRIMÄR] docs/reference/receipts/receipt-search-architecture.md, Zeilen 162-182 (Codeauszug) - Begründung: Zeigt `NamedQueryParameter`-Nutzung im tatsächlichen Code.
|
||||
- [PRIMÄR] src/backend/Centron.BL/Administration/Rights/AppRightsBL.cs, Zeilen 97-109 - Begründung: Weiteres, unabhängiges Beispiel desselben Musters.
|
||||
Prüfidee: Statische Codeanalyse (z. B. Regex-Suche nach String-Konkatenation mit `filter.` in SQL-Strings) über alle `*SearchConfiguration`- und `*BL`-Klassen; ergänzend automatisierter SQLi-Test gegen Such-Endpunkte.
|
||||
Tracelinks: StRS-18
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
|
||||
```
|
||||
ID: SyRS-20
|
||||
Titel: Zweisprachige Ressourcenhaltung (Deutsch/Englisch) für UI-Texte
|
||||
Ebene: SyRS
|
||||
Typ: nicht-funktional (ISO 25010: Benutzbarkeit)
|
||||
Akteur: System (Lokalisierungsschicht), Entwicklerteam
|
||||
Vorbedingung: Ein neuer UI-Text oder eine neue Fehlermeldung wird eingeführt.
|
||||
Fakt: Deutsche Basistexte liegen in `LocalizedStrings.resx`, englische Übersetzungen in `LocalizedStrings.en.resx`; Richtlinie schreibt vor, dass bei neuen Strings beide Sprachen gepflegt werden.
|
||||
Aussage: Das System soll alle benutzersichtbaren Texte über eine zweisprachige Resx-Ressourcenstruktur (Deutsch als Standard, Englisch als Alternative) bereitstellen.
|
||||
Ergebnis: Die Anwendung kann ohne Codeänderung zwischen Deutsch und Englisch umgeschaltet werden; deutsche Texte sind immer vollständig vorhanden (Default).
|
||||
Belege:
|
||||
- [SEKUNDÄR] docs/getting-started/general-structure.md, Zeilen 125-136 - Begründung: Dokumentierte Ressourcenstruktur und Pflegepflicht.
|
||||
Prüfidee: Stichprobe: für N zufällige Keys aus `LocalizedStrings.resx` prüfen, ob ein entsprechender Key in `LocalizedStrings.en.resx` existiert (Vollständigkeitsquote ermitteln).
|
||||
Tracelinks: StRS-19
|
||||
Konsolidierung: nein
|
||||
Status: belegt
|
||||
```
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# Traceability-Matrix — c-entron ERP RRE (V1 Baseline, Iteration 01)
|
||||
|
||||
Forward-Traceability: StRS → SyRS → SwRS. Backward-Traceability ist identisch über die `Tracelinks`-Felder in den jeweiligen Anforderungsdokumenten herstellbar (jede SyRS nennt ihre StRS, jede SwRS ihre SyRS).
|
||||
|
||||
Ein StRS/SyRS kann mehrere SwRS/SyRS haben; das ist in der Tabelle durch mehrere Zeilen mit derselben StRS-/SyRS-ID abgebildet.
|
||||
|
||||
| StRS-ID | SyRS-ID | SwRS-ID | Kern-Artefaktbeleg |
|
||||
|---|---|---|---|
|
||||
| StRS-01 | SyRS-01 | SwRS-01 | `ReceiptBase.cs` |
|
||||
| StRS-01 | SyRS-01 | SwRS-02 | `receipts-backend-architecture.md` (Critical Save Warning) |
|
||||
| StRS-02 | SyRS-02 | SwRS-03 | `ReceiptState.cs` |
|
||||
| StRS-02 | SyRS-02 | SwRS-04 | `ReceiptBL.cs:4936-4951` |
|
||||
| StRS-03 | SyRS-03 | SwRS-05 | `receipts-backend-architecture.md` (Version Tables) |
|
||||
| StRS-03 | SyRS-03 | SwRS-06 | `receipts-backend-architecture.md` (SaveAssetVersion SQL) |
|
||||
| StRS-04 | SyRS-04 | SwRS-07 | `receipt-search-architecture.md` (CreateSqlStatementAndParameters) |
|
||||
| StRS-04 | SyRS-04 | SwRS-08 | `receipt-search-architecture.md` (ShowRight-Prüfung) |
|
||||
| StRS-05 | SyRS-05 | SwRS-09 | `ReceiptContract.cs` / `contracts-backend.md` |
|
||||
| StRS-05 | SyRS-05 | SwRS-10 | `AutomaticFacturaBL.Contracts.cs` (dok.) |
|
||||
| StRS-06 | SyRS-06 | SwRS-11 | `Contract-Billing-RMM-Article-Logic.md` (Platzhaltererkennung) |
|
||||
| StRS-06 | SyRS-06 | SwRS-12 | `Contract-Billing-RMM-Article-Logic.md` (RMMServiceUnavailableException) |
|
||||
| StRS-07 | SyRS-07 | SwRS-13 | `ReceiptBL.cs:8646-8777` |
|
||||
| StRS-07 | SyRS-07 | SwRS-14 | `Customer.cs:45-47`, `AccountCustomer.cs` |
|
||||
| StRS-08 | SyRS-08 | SwRS-15 | `AccountBL.cs:192` [HYPOTHESE] |
|
||||
| StRS-09 | SyRS-09 | SwRS-16 | `AppRightsBL.cs:95-111` |
|
||||
| StRS-09 | SyRS-09 | SwRS-17 | `UserRightsConst.cs` / `add-a-new-right.md` |
|
||||
| StRS-10 | SyRS-10 | SwRS-18 | `PasswordManagerBL.cs:92-96` |
|
||||
| StRS-10 | SyRS-11 | SwRS-19 | `TwoFactorAuthenticationBL.cs:43-54` |
|
||||
| StRS-11 | SyRS-12 | SwRS-20 | `LicenseManager.cs:26-40` |
|
||||
| StRS-12 | SyRS-13 | SwRS-21 | `edi-architecture.md` (Partial-Class-Architektur) |
|
||||
| StRS-12 | SyRS-13 | SwRS-22 | `edi-architecture.md` (EdiDataType/EDIConnectionObjectKind) |
|
||||
| StRS-13 | SyRS-14 | SwRS-23 | `actionprice-system.md` (Validation Rules) |
|
||||
| StRS-14 | SyRS-15 | SwRS-24 | `ArticleBL.cs:99-123` |
|
||||
| StRS-15 | SyRS-16 | SwRS-25 | `zugferd-field-mapping.md` (Validation, ±3.00) |
|
||||
| StRS-15 | SyRS-16 | SwRS-26 | `zugferd-field-mapping.md` (Tax Category Codes) |
|
||||
| StRS-16 | SyRS-17 | SwRS-27 | `DeveloperSecurity.cs:8-46` |
|
||||
| StRS-17 | SyRS-18 | SwRS-28 | `general-structure.md` (Dual Implementation Architecture) |
|
||||
| StRS-18 | SyRS-19 | — | `receipt-search-architecture.md` / `AppRightsBL.cs` (kein eigenständiges SwRS, deckungsgleich mit SwRS-07/SwRS-16) |
|
||||
| StRS-19 | SyRS-20 | — | `general-structure.md` (Localization) — auf SwRS-Ebene nicht weiter konkretisiert (keine Code-Evidenz zu Resx-Vollständigkeit gefunden) |
|
||||
|
||||
## Nicht abgedeckte Verknüpfungen (offene Traceability-Lücken)
|
||||
|
||||
- **StRS-18 → SwRS**: Die SQL-Injection-Vermeidung ist bereits auf SwRS-Ebene durch SwRS-07 und SwRS-16 (beide nutzen `NamedQueryParameter`) belegt; es wurde bewusst kein zusätzliches, redundantes SwRS-Item erzeugt (siehe Konsolidierungsvermerk).
|
||||
- **StRS-19 → SwRS**: Keine SwRS-Konkretisierung, da keine Code-Evidenz zur tatsächlichen Vollständigkeit der `.en.resx`-Übersetzungen erhoben wurde (nur Richtlinie, keine Stichprobe durchgeführt). Als Lücke in `Analysebericht.md` vermerkt.
|
||||
|
||||
## Konsistenzcheck (siehe auch Analysebericht.md)
|
||||
|
||||
- Alle IDs (StRS-01..19, SyRS-01..20, SwRS-01..28) sind eindeutig vergeben; keine Duplikate gefunden.
|
||||
- Alle in StRS/SyRS/SwRS genannten Tracelinks verweisen auf tatsächlich existierende IDs in dieser Tabelle (manuell gegengeprüft).
|
||||
- Zwei SyRS-Anforderungen (SyRS-18, SyRS-19, SyRS-20) haben genau eine bzw. keine SwRS-Konkretisierung — dies ist beabsichtigt (architektur-/prozessweite Querschnittsanforderungen ohne einzelne, weitere Komponentenkonkretisierung) und keine fehlende Verknüpfung.
|
||||
+219
@@ -0,0 +1,219 @@
|
||||
# Messprotokoll – V1 (Baseline, solo) – Prompt-Version 01, Lauf 11 (Lauf E)
|
||||
|
||||
> V1-Messung im Agentenmodus `solo`. Teil eines Dreier-Parallelblocks (Läufe C, D, E), der die
|
||||
> V1-Reihe von zwei auf fünf Messpunkte bringt.
|
||||
>
|
||||
> **Parallelbetrieb:** Dieser Lauf lief zeitgleich mit `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180416_v3.3.0-5851`
|
||||
> und `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180417_v3.3.0-664e`. Drei Läufe konkurrierten um CPU, Netzwerk und
|
||||
> API-Kontingent. **Wanduhrzeit, `duration_ms` und `duration_api_ms` sind dadurch verzerrt**
|
||||
> und nicht mit seriellen Läufen vergleichbar. Tokens, Kosten, 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-25T18:04:55.8152741+02:00
|
||||
- **Endzeit:** 2026-08-25T18:21:24.9755573+02:00
|
||||
- **Dauer gesamt:** 00:16:29 (Wanduhr, **parallelbetriebsbedingt verzerrt**) bzw. 00:16:27 (`duration_ms`) — API: 00:15:49
|
||||
- **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.3.0-b676`
|
||||
- **Ablage:** `Iteration 1/claude-sonnet-5/solo/high/`
|
||||
- **Parallele Läufe:** ja – `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180416_v3.3.0-5851`, `Iteration 1/claude-sonnet-5/solo/high/01_Lauf_2026-08-25_180417_v3.3.0-664e`
|
||||
- **Skill-Version:** `3.3.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` — **nicht zur Laufzeit gesetzt**, sondern aus der Sitzung geerbt und
|
||||
nachträglich aus dem Session-Transkript rekonstruiert (95 Nachrichten, durchgängig `high`).
|
||||
`RawResult.json` enthält kein `effort`-Feld. Ab Skill-Version 3.4.0 wird der Wert per
|
||||
`--effort` explizit gesetzt.
|
||||
- **Modell:** `claude-sonnet-5` (vom Versuchsleiter vor dem Lauf gewählt); zusätzlich
|
||||
`claude-haiku-4-5-20251001` für interne Hilfsaufrufe (4.192 Input-/20 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)
|
||||
- **Fast-Mode:** aus
|
||||
|
||||
## Verbrauch
|
||||
|
||||
### Hauptagent (`usage`)
|
||||
| Messgröße | Wert |
|
||||
|---|---|
|
||||
| Input-Tokens | 64 |
|
||||
| Output-Tokens | 89.773 (davon 11.962 Thinking-Tokens) |
|
||||
| Cache-Write-Tokens | 221.931 |
|
||||
| Cache-Read-Tokens | 4.734.615 |
|
||||
| Agent-Turns | 67 |
|
||||
|
||||
### Gesamtlauf (`modelUsage`, abrechnungsrelevant)
|
||||
| Messgröße | `claude-sonnet-5` | `claude-haiku-4-5-20251001` | Summe |
|
||||
|---|---:|---:|---:|
|
||||
| Input-Tokens | 64 | 4.192 | 4.256 |
|
||||
| Output-Tokens | 89.773 | 20 | 89.793 |
|
||||
| Cache-Write-Tokens | 221.931 | 0 | 221.931 |
|
||||
| Cache-Read-Tokens | 4.734.615 | 0 | 4.734.615 |
|
||||
| Tokens gesamt | 5.046.383 | 4.212 | **5.050.595** |
|
||||
|
||||
**Tokens gesamt: 5.050.595** (Summe aus Input, Output, Cache-Write und Cache-Read ueber alle Modelle; `total_cost_usd` steht weiterhin in `RawResult.json`)
|
||||
|
||||
Ohne Subagenten sind Haupt- und Gesamtwerte für `claude-sonnet-5` identisch.
|
||||
|
||||
## Ergebnis
|
||||
- **Status:** erfolgreich (`is_error: false`, `terminal_reason: "completed"`,
|
||||
`stop_reason: "end_turn"`, Exit-Code 0, `Stderr.log` leer)
|
||||
- **Session-ID:** `a07cf6c4-5148-42fe-b36e-654e1e860dd3`
|
||||
- **Permission-Denials:** **0** – auch keine auf `Task`/`Agent`/`Workflow`
|
||||
- **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` | 34.041 B | 19 Anforderungen |
|
||||
| `SyRS.md` | 31.202 B | 20 Anforderungen |
|
||||
| `SwRS.md` | 39.580 B | 28 Anforderungen |
|
||||
| `Traceability.md` | 4.061 B | 31 Datenzeilen |
|
||||
| `Hypothesen.md` | 2.716 B | Sammlung der `[HYPOTHESE]`-Aussagen |
|
||||
| `Glossar.md` | 6.417 B | Domänenbegriffe |
|
||||
| `Analysebericht.md` | 16.650 B | Modulabdeckung, Konsistenzcheck, Selbstbewertung |
|
||||
|
||||
Summe: **67 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`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 19 | 28,4 % |
|
||||
| SyRS | 20 | 29,9 % |
|
||||
| SwRS | 28 | 41,8 % |
|
||||
| **Gesamt** | **67** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 32 | 47,8 % |
|
||||
| Sicherheit | 12 | 17,9 % |
|
||||
| Daten | 11 | 16,4 % |
|
||||
| Schnittstelle | 5 | 7,5 % |
|
||||
| nicht-funktional (Zuverlässigkeit/Betriebssicherheit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Wartbarkeit/Übertragbarkeit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Benutzbarkeit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Sicherheit / Zuverlässigkeit, ISO 25010: Sicherheit) | 1 | 1,5 % |
|
||||
| Schnittstelle (ISO 25010: Übertragbarkeit/Wartbarkeit) | 1 | 1,5 % |
|
||||
| Sicherheit (ISO 25010: Sicherheit) | 1 | 1,5 % |
|
||||
| (1 weitere) | 1 | 1,5 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 87 |
|
||||
| davon `PRIMÄR` | 49 (56,3 %) |
|
||||
| davon `SEKUNDÄR` | 32 (36,8 %) |
|
||||
| davon `KONTEXT` | 6 (6,9 %) |
|
||||
| Belege je Anforderung (Median) | 1 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 42 (62,7 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 64 | 95,5 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 3 | 4,5 % |
|
||||
| als Workaround vermerkt | 3 | 4,5 % |
|
||||
| Konsolidierungskandidaten | 2 | 3,0 % |
|
||||
| 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]` | **verletzt** – 5 von 31 ungedeckt: StRS-17, SyRS-05, SyRS-18, SwRS-10, SwRS-26 |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 67 von 67 mit Tracelinks (100,0 %) |
|
||||
|
||||
## V1-Reihe: fünf Messpunkte unter identischer Bedingung
|
||||
|
||||
| | Lauf A | Lauf B | **Lauf C** | **Lauf D** | **Lauf E** |
|
||||
|---|---:|---:|---:|---:|---:|
|
||||
| Anforderungen | 42 | 82 | **60** | **73** | **67** |
|
||||
| — StRS/SyRS/SwRS | 14/15/13 | 20/34/28 | **17/19/24** | **18/24/31** | **19/20/28** |
|
||||
| Tokens gesamt | 4.357.855 | 12.598.503 | **5.659.692** | **4.591.733** | **5.050.595** |
|
||||
| Output-Tokens | 70.749 | 129.077 | **95.147** | **103.814** | **89.793** |
|
||||
| Thinking-Tokens | 10.470 | 21.863 | **14.407** | **22.957** | **11.962** |
|
||||
| Cache-Read | 4,12 M | 12,23 M | **5,35 M** | **4,33 M** | **4,73 M** |
|
||||
| Agent-Turns | 68 | 107 | **72** | **77** | **67** |
|
||||
| Traceability-Zeilen | 19 | 36 | **39** | **33** | **31** |
|
||||
| Denials / Subagenten | 0 / 0 | 0 / 0 | **0 / 0** | **0 / 0** | **0 / 0** |
|
||||
|
||||
**V1 gesamt:** Anforderungen 42–82 (Median 67), Tokens 4.357.855–12.598.503 (Median 5.050.595).
|
||||
|
||||
## Vergleich V1 (solo) gegen V1b (builtin)
|
||||
|
||||
| | V1 (5 Läufe) | V1b (4 vollständige Läufe) |
|
||||
|---|---|---|
|
||||
| Anforderungen | 42 – 82 (Faktor **2,0**) | 55 – 325 (Faktor **5,9**) |
|
||||
| Tokens gesamt | 4.357.855 – 12.598.503 (Faktor **2,9**) | 11.516.200 – 52.713.542 (Faktor **4,6**) |
|
||||
| Median Tokens | **5.050.595** | **30.065.183** |
|
||||
| Subagenten | 0 (erzwungen) | 0 – 14 (selbstgewählt) |
|
||||
|
||||
## Anmerkungen/Auffälligkeiten
|
||||
|
||||
1. **V1 ist deutlich stabiler als V1b.** Die drei parallelen Läufe C, D und E liegen bei 60, 73
|
||||
und 67 Anforderungen und 2,86, 2,54 und 5.050.595 Tokens – eine Spanne von nur ±11 % bzw. ±6 %.
|
||||
Über alle fünf V1-Läufe beträgt die Streuung Faktor 2,0 (Anforderungen) und 2,9 (Tokens),
|
||||
gegenüber Faktor 5,9 und 4,6 in V1b. **Die selbstgewählte Zerlegung in Subagenten ist damit
|
||||
als Hauptursache der V1b-Streuung bestätigt:** Wird sie unterbunden, schrumpft die Streuung
|
||||
auf weniger als die Hälfte.
|
||||
|
||||
2. **V1 kostet ein Vielfaches weniger.** Median 5.050.595 Tokens gegenüber 30.065.183 in V1b, und
|
||||
selbst der teuerste V1-Lauf (12.598.503 Tokens) liegt unter dem günstigsten V1b-Lauf (11.516.200 Tokens).
|
||||
Ursache sind die deutlich niedrigeren Cache-Read-Tokens: 4,1 bis 12,2 Mio. gegenüber 10,5 bis
|
||||
44,8 Mio. Ohne parallele Kontexte entfällt das mehrfache Einlesen derselben Artefakte.
|
||||
|
||||
3. **Lauf B bleibt der Ausreißer der V1-Reihe.** Mit 82 Anforderungen, 12.598.503 Tokens und 12,23 Mio.
|
||||
Cache-Reads liegt er deutlich über den vier übrigen V1-Läufen, die eng zwischen 42 und 73
|
||||
bzw. 2,20 und 5.659.692 Tokens liegen. Bei fünf Messpunkten ist das noch nicht als Ausreißer im
|
||||
statistischen Sinn zu behandeln, aber als Beobachtung festzuhalten.
|
||||
|
||||
4. **Effort war durchgängig `high`** – für alle drei Läufe aus den Transkripten belegt
|
||||
(95 bis 117 Nachrichten je Lauf). Der Denkaufwand scheidet damit als Erklärung für
|
||||
verbleibende Unterschiede innerhalb der V1-Reihe aus.
|
||||
|
||||
5. **Dreifachparallelität technisch fehlerfrei.** Alle drei Läufe schrieben in getrennte
|
||||
Verzeichnisse mit eigenem `_meta`. Keine Kollision, keine gegenseitige Überschreibung, alle
|
||||
drei Ergebnisverzeichnisse frei von Fremddateien, Root unverändert. Das Verfahren aus
|
||||
Skill-Version 3.1.0 skaliert auch über zwei gleichzeitige Läufe hinaus.
|
||||
|
||||
6. **Wanduhrzeiten nicht auswerten.** Alle drei Läufe brauchten 16:29 bis 17:49 – bei drei
|
||||
konkurrierenden Prozessen auf einer Maschine ist das kein inhaltliches Signal. Für
|
||||
Laufzeitvergleiche seriell messen.
|
||||
|
||||
7. **Manuelle Eingriffe während des Laufs:** keine.
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"is_error":false,"duration_api_ms":948607,"num_turns":67,"stop_reason":"end_turn","session_id":"a07cf6c4-5148-42fe-b36e-654e1e860dd3","total_cost_usd":2.7367969999999997,"usage":{"input_tokens":64,"cache_creation_input_tokens":221931,"cache_read_input_tokens":4734615,"output_tokens":89773,"output_tokens_details":{"thinking_tokens":11962},"server_tool_use":{"web_search_requests":0,"web_fetch_requests":0},"service_tier":"standard","cache_creation":{"ephemeral_1h_input_tokens":221931,"ephemeral_5m_input_tokens":0},"inference_geo":"not_available","iterations":[{"input_tokens":2,"output_tokens":593,"cache_read_input_tokens":248255,"cache_creation_input_tokens":1399,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":1399},"type":"message"}],"speed":"standard"},"modelUsage":{"claude-haiku-4-5-20251001":{"inputTokens":4192,"outputTokens":20,"cacheReadInputTokens":0,"cacheCreationInputTokens":0,"webSearchRequests":0,"costUSD":0.004292000000000001,"contextWindow":200000,"maxOutputTokens":32000,"canonicalModel":"claude-haiku-4-5","provider":"firstParty"},"claude-sonnet-5":{"inputTokens":64,"outputTokens":89773,"cacheReadInputTokens":4734615,"cacheCreationInputTokens":221931,"webSearchRequests":0,"costUSD":2.7325049999999997,"contextWindow":1000000,"maxOutputTokens":64000,"canonicalModel":"claude-sonnet-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":"All seven deliverables are written to the specified output directory, and the analyzed codebase remains untouched (clean git status).\n\n**Summary of the run:**\n\nGiven the scale of the codebase (16,063 C# files, ~90 business-logic modules), I prioritized depth over breadth on seven core areas with strong evidentiary support rather than attempting shallow coverage of everything: Sales/receipts (offer→order→delivery→invoice chain, status machine, versioning, search), contracts & recurring/RMM-based billing, security/rights, licensing, warehouse stock rights, EDI supplier integration, and e-invoicing (ZUGFeRD/XRechnung).\n\nProduced in `Ergebnisse/`:\n- **StRS.md** (19 requirements), **SyRS.md** (20), **SwRS.md** (28) — each with full Fakt/Aussage/Belege/Prüfidee per the mandated format, PRIMÄR evidence (actual source lines) required and provided for every security/rights/billing requirement except one\n- **Traceability.md** — full StRS→SyRS→SwRS matrix plus a documented consistency check (no duplicate IDs, no unbacked requirements, no dangling tracelinks)\n- **Hypothesen.md** — the one requirement lacking PRIMÄR enforcement evidence (dunning-level order lock) flagged transparently with the specific missing information\n- **Glossar.md** — domain terms\n- **Analysebericht.md** — an honest coverage map showing exactly what was deeply analyzed vs. only documented vs. not touched at all (notably: the entire WPF UI client, ~900-file Administration module, all external API integrations, and deployment/CI-CD artifacts), plus concrete recommendations for a follow-up iteration.","ttft_ms":4845,"ttft_stream_ms":2715,"time_to_request_ms":40,"type":"result","duration_ms":987418,"uuid":"7b04ed12-4e04-4b85-8349-b490fb155eb9","queued_turn_count":0}
|
||||
+1161
File diff suppressed because it is too large
Load Diff
+66
@@ -0,0 +1,66 @@
|
||||
## Gefundene Anforderungen
|
||||
|
||||
Maschinell aus `Ergebnisse\StRS.md`, `SyRS.md` und `SwRS.md` ausgewertet (Blockformat des Prompts). Erzeugt von `analyse-anforderungen.py`.
|
||||
|
||||
Die Kenngrößen decken die **maschinell prüfbare** Hälfte des Evaluationsrahmens aus Kapitel 4.3 ab: Belegqualität und Übernahmewürdigkeit gehören zur *Statement-Qualität*, Verteilung und Konsolidierungskandidaten zur *Set-Qualität*, Tracelinks und Belegklassifikation zur *Traceability-Qualität*. Die Expertenbewertung nach Likert-Skala tritt daneben und wird hier nicht ersetzt.
|
||||
|
||||
### Verteilung über die Ebenen
|
||||
|
||||
| Ebene | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| StRS | 19 | 28,4 % |
|
||||
| SyRS | 20 | 29,9 % |
|
||||
| SwRS | 28 | 41,8 % |
|
||||
| **Gesamt** | **67** | 100 % |
|
||||
|
||||
### Anforderungstypen
|
||||
|
||||
| Typ | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| funktional | 32 | 47,8 % |
|
||||
| Sicherheit | 12 | 17,9 % |
|
||||
| Daten | 11 | 16,4 % |
|
||||
| Schnittstelle | 5 | 7,5 % |
|
||||
| nicht-funktional (Zuverlässigkeit/Betriebssicherheit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Wartbarkeit/Übertragbarkeit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Benutzbarkeit) | 1 | 1,5 % |
|
||||
| nicht-funktional (Sicherheit / Zuverlässigkeit, ISO 25010: Sicherheit) | 1 | 1,5 % |
|
||||
| Schnittstelle (ISO 25010: Übertragbarkeit/Wartbarkeit) | 1 | 1,5 % |
|
||||
| Sicherheit (ISO 25010: Sicherheit) | 1 | 1,5 % |
|
||||
| (1 weitere) | 1 | 1,5 % |
|
||||
|
||||
### Belegqualität
|
||||
|
||||
| Messgröße | Wert |
|
||||
|---|---:|
|
||||
| Belege gesamt | 87 |
|
||||
| davon `PRIMÄR` | 49 (56,3 %) |
|
||||
| davon `SEKUNDÄR` | 32 (36,8 %) |
|
||||
| davon `KONTEXT` | 6 (6,9 %) |
|
||||
| Belege je Anforderung (Median) | 1 |
|
||||
| Anforderungen mit mindestens einem `PRIMÄR`-Beleg | 42 (62,7 %) |
|
||||
|
||||
### Übernahmewürdigkeit
|
||||
|
||||
**nicht erhoben** – das Feld `Übernahmewürdigkeit` wurde erst mit der Prompt-Fassung vom 2026-08-26 eingeführt und liegt für diesen Lauf nicht vor. Hinweise auf Workarounds stecken ersatzweise im Feld `Status`.
|
||||
|
||||
### Status
|
||||
|
||||
| Kategorie | Anzahl | Anteil |
|
||||
|---|---:|---:|
|
||||
| belegt | 64 | 95,5 % |
|
||||
| als `HYPOTHESE` gekennzeichnet | 3 | 4,5 % |
|
||||
| als Workaround vermerkt | 3 | 4,5 % |
|
||||
| Konsolidierungskandidaten | 2 | 3,0 % |
|
||||
| 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]` | **verletzt** – 5 von 31 ungedeckt: StRS-17, SyRS-05, SyRS-18, SwRS-10, SwRS-26 |
|
||||
| **Verifizierbarkeit** – jede Anforderung mit Prüfidee oder Akzeptanzkriterium | **erfüllt** |
|
||||
| **Übernahmewürdigkeit** – Einstufung für die Migrationsperspektive | *nicht erhoben* (Feld erst ab Prompt-Fassung 2026-08-26) |
|
||||
| **Traceability** – Verknüpfung zwischen den Ebenen | 67 von 67 mit Tracelinks (100,0 %) |
|
||||
|
||||
+1
@@ -0,0 +1 @@
|
||||
|
||||
+132
@@ -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_180418_sonnet5_solo_v3.3.0-b676\Ergebnisse\`.
|
||||
Verändere keine Dateien im Arbeitsverzeichnis (der analysierten Codebasis).
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:21:24.9755573+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
2026-08-25T18:04:55.8152741+02:00
|
||||
+1
@@ -0,0 +1 @@
|
||||
[]
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
# Subagenten-Aufrufe
|
||||
|
||||
Session `a07cf6c4-5148-42fe-b36e-654e1e860dd3`, Transkript `a07cf6c4-5148-42fe-b36e-654e1e860dd3.jsonl`.
|
||||
|
||||
`subagent_stats`: **0** Subagenten gesamt, davon **0** von Subagenten gestartet (max_depth 0). Direkt vom Hauptagenten erwartet: **0**. Im Transkript gefunden: **0**.
|
||||
Reference in New Issue
Block a user