From 1376779224027960245584a9a6d9511348d7661e Mon Sep 17 00:00:00 2001 From: Stefan Date: Fri, 5 Jun 2026 14:45:39 +0200 Subject: [PATCH] Docs: update ARCHITECTURE + copilot instructions, add CLAUDE.md + USER_GUIDE - ARCHITECTURE.md: reflect the implemented DI service layer, CAMTParser, OpenTelemetry/observability, the ported report engine, and CAMT+MT940 banking; mark the resolved observations. - copilot-instructions.md: add Services/DI, dual-format banking, observability and testing sections; add an Instruction-Sync banner. - CLAUDE.md (new): Claude Code project instructions mirroring the shared rules, plus build/test workflow notes. Both files state they must stay in sync. - USER_GUIDE.md (new, Fuchs/Docs): end-user process guide (login, invoices, reminders, requests, banking incl. MT940/CAMT upload, DATEV, reports). Co-Authored-By: Claude Opus 4.8 --- .github/copilot-instructions.md | 28 +++++++ CLAUDE.md | 60 +++++++++++++++ Fuchs/Docs/ARCHITECTURE.md | 49 +++++++++--- Fuchs/Docs/USER_GUIDE.md | 128 ++++++++++++++++++++++++++++++++ 4 files changed, 255 insertions(+), 10 deletions(-) create mode 100644 CLAUDE.md create mode 100644 Fuchs/Docs/USER_GUIDE.md diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md index 69b5b38..1a1babc 100644 --- a/.github/copilot-instructions.md +++ b/.github/copilot-instructions.md @@ -1,5 +1,13 @@ # Copilot Instructions +> ## ⚠️ Instruction Sync +> This file (`.github/copilot-instructions.md`) and the Claude Code instructions +> (`/CLAUDE.md`) are **two views of the same project rules and must stay in sync**. +> Whenever you change one, make the equivalent change in the other in the same +> commit. `CLAUDE.md` may add tool-specific workflow notes, but the shared +> project facts (architecture, coding standards, configuration, libraries, +> secrets, observability) must match. + ## Project Overview - **Fuchs Intranet** is an ASP.NET Core (.NET 10) web application — the intranet IS the entire website, served from `/`. - Routes: `/{fn?}/{id?}/{code?}` → `IntranetController.Index`; `/do/{fn?}/{id?}/{code?}` → `IntranetController.Do`. @@ -31,6 +39,26 @@ - Do not use OCMS or OCMS_sharp; use only OCORE or OCORE_web. - For builds failing due to SixLabors.ImageSharp requiring a license (v4.0.0+), check copilot-instructions.md for the SixLabors license key/handling info before downgrading ImageSharp. +## Services & Dependency Injection +- Business logic lives in **DI-registered services** under `Fuchs/Services/` behind interfaces; inject them into `IntranetController` (constructor injection). Do **not** reintroduce static God-classes or pass the whole controller into helpers. + - `IComService` (email/SMS via ProcessWeb Mailer API, attachments sent inline as base64), `IPdfService` (MigraDoc render), `IInvoiceService`, `IReminderService`, `IReportService` (SQL report engine via `FuchsVisualization`), `IWidgetService`, `IBankingService`, `IMfrClientFactory`. + - Lifetimes: stateless services (`IPdfService`, `IBankingService`, `IMfrClientFactory`) are singletons; request-scoped DB services (`IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IComService`) are scoped. Register in `Program.cs`. +- `FdsInvoiceData` / `FdsReminderData` are **pure data holders** (parse + properties). Loading, persistence and PDF generation belong in the services — never `Task.Run(...).Wait()` sync-over-async. +- Data access stays SQL-first via OCORE helpers (`getSQLDataSet_async`, `setSQLValue_async`) + stored procedures; no EF Core. + +## Bank statement parsing (MT940 + CAMT) +- Two parsers feed the same banking pipeline: the external `MT940Parser` (SWIFT text) and the in-repo **`CAMTParser`** project (ISO 20022 camt.052/053/054 XML). +- `BankingService.ParseToDatatable` **auto-detects** the format (XML → CAMT, else MT940) and maps both into the `fds__tt__bankingtransactions` schema. The `bam/up` handler and the frontend file picker accept both (`.sta/.mt940/.txt` and `.xml/.camt`). +- `CAMTParser` is namespace-agnostic (matches elements by local name) so it handles every camt schema version. Keep both parsers' column mappings aligned when changing the banking schema. + +## Observability +- Use **OpenTelemetry**. The app's instrumentation is centralised in `Fuchs/Observability/FuchsTelemetry.cs` (one `ActivitySource` + one `Meter`). +- When adding a meaningful operation: start an activity (`FuchsTelemetry.StartActivity(...)`), record the relevant counter/histogram, and log entry/result/timing/errors via the injected `ILogger`. Prefer structured logging (named placeholders), never string interpolation in log messages. +- Tracing/metrics are always collected; OTLP export is opt-in via `Fuchs:Telemetry:OtlpEndpoint`. Don't add exporters that fail hard when no collector is present. + +## Testing +- xUnit in `Fuchs.Tests`. For every service/handler change add tests covering **both** an intentionally succeeding and an intentionally failing path where feasible (use stubs/mocks; the test project has `InternalsVisibleTo`). DB-bound paths that can't be unit-tested should at least have their pure logic covered. + ## Azure Key Vault — Secret Naming - Secret names must satisfy the pattern `^[0-9a-zA-Z-]+$` (alphanumerics and hyphens only; no underscores, dots, or spaces). - Hierarchy levels are separated by `--` (double hyphen), which maps to `:` in `IConfiguration`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..4360a52 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,60 @@ +# CLAUDE.md — Project instructions for Claude Code + +> ## ⚠️ Instruction Sync +> This file and **`.github/copilot-instructions.md`** are two views of the same +> project rules and **must stay in sync**. When you change a shared rule +> (architecture, coding standards, configuration, libraries, secrets, +> observability, testing), make the equivalent change in **both files in the +> same commit**. This file may add Claude Code / workflow specifics; the shared +> project facts must match `copilot-instructions.md`. + +## Project Overview +- **Fuchs Intranet** — ASP.NET Core (**.NET 10**) web app; the intranet IS the whole website, served from `/`. +- Routes: `/{fn?}/{id?}/{code?}` → `IntranetController.Index`; `/do/{fn?}/{id?}/{code?}` → `IntranetController.Do` (dispatches by `fn` to `Do_Process_*`). +- Solution `Fuchs_Intranet.slnx`. Key projects: `Fuchs` (web), `Fuchs_DataService` (MFR sync worker), `MFR_RESTClient`, `CAMTParser`, `Fuchs.Tests`, and the OCORE submodules (`OCORE`, `OCORE_web`, `OCORE_web_pdf`, `OCORE_Charting`). `MT940Parser` is an external referenced project. + +## Build & Test (workflow) +- Build app: `dotnet build Fuchs/Fuchs.csproj -c Debug`. Build all: `dotnet build Fuchs_Intranet.slnx -c Debug`. +- Test: `dotnet test Fuchs.Tests/Fuchs.Tests.csproj -c Debug`. +- Always build **and** run the test suite before committing. The build emits many pre-existing analyzer/platform warnings (CA1416 etc.) — those are expected; only treat `: error` lines as failures. +- Commit only when asked. Co-author trailer: `Co-Authored-By: Claude Opus 4.8 `. +- The working tree may contain an untracked `Fuchs_Database/` SQL project — it is **not** part of app changes; never `git add -A` it into an unrelated commit. Stage explicit paths. + +## Coding Standards +- C# only. Modern, performance-oriented .NET 10 (async/await, LINQ, DI). +- Keep files ≤ 400 (max 600) lines; refactor larger files into focused classes. +- PascalCase types/methods, camelCase locals/params. + +## Configuration +- All settings in `Fuchs/appsettings.json` — **never** `Web.config` / `System.Configuration.ConfigurationManager`. App settings nested under `"Fuchs"`; connection strings under `"ConnectionStrings"`. +- `FuchsOcmsIntranet.Initialize(configuration)` runs in `Program.cs` before DI registration. +- `appsettings.Development.json` (git-ignored) overrides secrets locally. + +## Libraries +- Do **not** upgrade Spire.PDF beyond 8.10.5. Prefer OCORE / OCORE_web / OCORE_web_pdf helpers over rewriting. Do not use OCMS/OCMS_sharp — OCORE only. + +## Services & Dependency Injection +- Business logic lives in **DI-registered services** under `Fuchs/Services/` behind interfaces, injected into `IntranetController`. Do not reintroduce static God-classes or pass the controller into helpers. +- Services: `IComService`, `IPdfService`, `IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IBankingService`, `IMfrClientFactory`. Stateless ones are singletons; DB/request-scoped ones are scoped (see `Program.cs`). +- `FdsInvoiceData` / `FdsReminderData` are **pure data holders**; load/persist/render belongs in services. No `Task.Run(...).Wait()` sync-over-async. +- Data access is SQL-first via OCORE helpers + stored procedures (no EF Core). + +## Bank statement parsing (MT940 + CAMT) +- `MT940Parser` (external, SWIFT text) and **`CAMTParser`** (in-repo, ISO 20022 camt.052/053/054 XML) feed the same pipeline. +- `BankingService.ParseToDatatable` auto-detects (XML → CAMT, else MT940) → `fds__tt__bankingtransactions`. `bam/up` + the frontend accept both formats. `CAMTParser` is namespace-agnostic. Keep both column mappings aligned with the banking schema. + +## Observability +- OpenTelemetry. Instrumentation is centralised in `Fuchs/Observability/FuchsTelemetry.cs` (one `ActivitySource`, one `Meter`). +- For meaningful operations: start an activity, record the matching counter/histogram, and log entry/result/timing/errors via injected `ILogger` using **structured** placeholders (never interpolated strings). +- Always collected; OTLP export opt-in via `Fuchs:Telemetry:OtlpEndpoint`. No exporters that hard-fail without a collector. + +## Testing +- xUnit in `Fuchs.Tests`. For each service/handler change, add tests for **both** an intentionally succeeding and an intentionally failing path where feasible (stubs/mocks; `InternalsVisibleTo` is enabled). Cover pure logic for DB-bound paths that can't be unit-tested. + +## Secrets (Azure Key Vault) +- Full naming rules live in `.github/copilot-instructions.md` (kept in sync). In short: names match `^[0-9a-zA-Z-]+$`, hierarchy via `--` (→ `:`), underscores → `-`, app prefix `fuchs`; register new keys in `ManagedSecretKeys` in `appsettings.json`. + +## Documentation map +- `Fuchs/Docs/ARCHITECTURE.md` — solution architecture (keep current when structure changes). +- `Fuchs/Docs/USER_GUIDE.md` — end-user process guide. +- `.github/instructions/*.instructions.md` — domain-specific contributor guidance. diff --git a/Fuchs/Docs/ARCHITECTURE.md b/Fuchs/Docs/ARCHITECTURE.md index 4ca1188..b02d2b6 100644 --- a/Fuchs/Docs/ARCHITECTURE.md +++ b/Fuchs/Docs/ARCHITECTURE.md @@ -18,7 +18,8 @@ The **Fuchs Intranet** solution is a line-of-business web application for **Seba | **OCORE_web** | Class Library (shared) | Web utilities: MVC helpers, middleware, auth, captcha | | **OCORE_web_pdf** | Class Library (shared) | PDF generation (MigraDoc/PDFsharp, HTML→PDF) | | **OCORE_Charting** | Class Library (shared) | Data visualization / charting (ported System.Windows.Forms.DataVisualization) | -| **MT940Parser** | Class Library (shared) | SWIFT MT940/MT942 bank statement parser | +| **MT940Parser** | Class Library (external) | SWIFT MT940/MT942 bank statement parser | +| **CAMTParser** | Class Library (in-repo) | ISO 20022 CAMT (camt.052/053/054) bank statement parser | **All projects target `net10.0`.** @@ -163,8 +164,12 @@ OCORE_Charting (standalone — referenced by solution but no direct project ref ### 4.2 Singleton Configuration Object `Fuchs_intranet` is a manually-managed singleton (via `FuchsOcmsIntranet`) initialized at startup with `IConfiguration`. It holds connection strings, app settings, auth helpers, and DB connection factory methods. -### 4.3 Static Business Logic Classes -Most business logic lives in **static classes** (`FuchsPdf`, `FuchsWidgets`, `FuchsReports`, `FuchsFdsEmail`, `Banking`) that receive the controller instance or `Fuchs_intranet` as a parameter. This is a legacy pattern from the VB.NET conversion. +### 4.3 Service Layer (Dependency Injection) +Business logic lives in **DI-registered services** under `Fuchs/Services/` behind interfaces, injected into `IntranetController`: +`IComService`, `IPdfService`, `IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IBankingService`, `IMfrClientFactory`. +Stateless services (`IPdfService`, `IBankingService`, `IMfrClientFactory`) are singletons; DB/request-scoped services are scoped (see `Program.cs`). +`FdsInvoiceData` / `FdsReminderData` are now **pure data holders** (parse + properties); loading, persistence and PDF generation live in the services (fully async — no `Task.Run(...).Wait()`). +`FuchsPdf` / `FuchsVisualization` remain as static rendering libraries used *by* the services. The earlier static, controller-coupled helpers (`FuchsWidgets`, `FuchsReports`, `Banking`, `FuchsFdsEmail`) have been removed. ### 4.4 SQL-First Data Access There is no ORM (no EF Core). All data access uses **ADO.NET via OCORE SQL helpers** (`getSQLDatatable_async`, `getSQLDataSet_async`, `setSQLValue_async`) calling stored procedures and inline SQL. `DataTable`/`DataRow` is the primary data transfer mechanism. @@ -177,9 +182,17 @@ Cookie-based authentication (`CookieAuthenticationDefaults`) with custom claims --- -## 5. DI Service Extraction Candidates +## 5. Service Layer (implemented) -The following static classes and tightly-coupled code sections are strong candidates for refactoring into proper DI-registered services. This improves testability, decouples dependencies, and aligns with ASP.NET Core best practices. +> **Status: DONE.** The services below are implemented and DI-registered in +> `Program.cs`. The original extraction rationale is retained for reference / +> history. `FuchsFdsEmail` → `IComService` (ProcessWeb Mailer API, inline +> base64 attachments), `FuchsWidgets` → `IWidgetService`, `FuchsPdf` → +> `IPdfService`, `Banking` → `IBankingService` (now MT940 **and** CAMT), +> `FdsInvoiceData`/`FdsReminderData` → `IInvoiceService`/`IReminderService` +> (data classes are now pure POCOs), `FuchsReports` → `IReportService` +> (backed by the ported `FuchsVisualization` engine), `FdsMfrClient` → +> `IMfrClientFactory`. --- @@ -391,8 +404,24 @@ public class MfrClientFactory : IMfrClientFactory, IDisposable ## 7. Additional Observations -1. **`System.Configuration.ConfigurationManager` usage** in `FuchsFdsEmail.cs` directly violates the project's coding standards (`appsettings.json` only). -2. **No dependency injection in `FdsInvoiceData`/`FdsReminderData`** — these classes receive the entire controller, creating circular-style dependencies. -3. **`FdsMfrClient` is `new`-ed directly** in controller partials (e.g., `IntranetController.Invoices2.cs`) instead of being injected. -4. **`OCORE_Charting`** is in the solution but not directly referenced by any project — verify if it's still needed. -5. **Topshelf** in `Fuchs_DataService` could be replaced with native `dotnet` Worker Service hosting for .NET 10 alignment. +1. ✅ **Resolved** — email/SMS moved off `ConfigurationManager` into `IComService` (ProcessWeb Mailer API). +2. ✅ **Resolved** — `FdsInvoiceData`/`FdsReminderData` are now pure data holders; DB + PDF logic moved to `IInvoiceService`/`IReminderService`. +3. ✅ **Resolved** — `FdsMfrClient` is created via `IMfrClientFactory` (no `new` in controllers). +4. ✅ **Resolved** — `OCORE_Charting` is now used (transitively, via `OCORE_web`'s chart engine) by the report renderer (`FuchsVisualization`). +5. ⏳ **Open** — **Topshelf** in `Fuchs_DataService` could be replaced with native `dotnet` Worker Service hosting for .NET 10 alignment. + +--- + +## 8. Observability (OpenTelemetry) + +- Instrumentation is centralised in `Fuchs/Observability/FuchsTelemetry.cs`: one `ActivitySource` and one `Meter` (`Fuchs.Intranet`). +- **Metrics** — counters (`fuchs.invoices.rendered`, `fuchs.reminders.rendered`, `fuchs.reports.rendered`, `fuchs.emails.sent`/`.failed`, `fuchs.sms.sent`, `fuchs.banking.mt940.rows`, `fuchs.mfr.calls`) and duration histograms (`fuchs.pdf.render.duration`, `fuchs.report.render.duration`, `fuchs.email.send.duration`). +- **Tracing** — ASP.NET Core, HttpClient and SqlClient instrumentation plus the app `ActivitySource`; services start spans for their key operations. +- Configured in `Program.cs`. Always collected in-process; **OTLP export is opt-in** via `Fuchs:Telemetry:OtlpEndpoint` (and can be disabled with `Fuchs:Telemetry:Enabled=false`), so a missing collector never affects the app. +- All services + handlers log entry/result/timing/errors via `ILogger` with structured placeholders. + +## 9. Bank Statement Parsing (MT940 + CAMT) + +- `BankingService` (`IBankingService`) accepts **both** MT940 (SWIFT text, via the external `MT940Parser`) and **CAMT** (ISO 20022 camt.052/053/054 XML, via the in-repo `CAMTParser`). +- `ParseToDatatable` **auto-detects** the format from content (XML → CAMT, else MT940) and maps either into the `fds__tt__bankingtransactions` schema; the `bam/up` handler and the frontend upload accept both. +- `CAMTParser` matches elements by **local name** (namespace-agnostic) so it works across every camt schema version. When the banking schema changes, keep the MT940 and CAMT column mappings in `BankingService` aligned. diff --git a/Fuchs/Docs/USER_GUIDE.md b/Fuchs/Docs/USER_GUIDE.md new file mode 100644 index 0000000..af0eb13 --- /dev/null +++ b/Fuchs/Docs/USER_GUIDE.md @@ -0,0 +1,128 @@ +# Fuchs Intranet — Benutzerhandbuch + +> Praxisleitfaden für Mitarbeiter:innen der Firma Sebastian Fuchs Bad und Heizung. +> Beschreibt die täglichen Abläufe im Intranet. Technische Details siehe +> `ARCHITECTURE.md`. + +--- + +## 1. Anmeldung & Konto + +### Anmelden +1. Intranet im Browser öffnen. +2. E-Mail-Adresse und Passwort eingeben → **Anmelden**. +3. Die Sitzung bleibt 8 Stunden aktiv (gleitend). + +### Passwort vergessen +1. „Passwort vergessen" wählen, **Nachname** und **E-Mail** eingeben. +2. Es wird ein Bestätigungscode per **SMS** an die hinterlegte Mobilnummer gesendet. +3. Code eingeben → das Passwort wird per E-Mail zugesandt. + *(Aus Sicherheitsgründen erfolgt keine Rückmeldung, ob die Adresse existiert.)* + +### Passwort ändern +1. Konto → **Passwort ändern**. +2. Bestätigungscode per SMS anfordern und eingeben. +3. Altes Passwort + neues Passwort (mind. 6 Zeichen) zweimal eingeben. + Das alte Passwort und die Code-Bestätigung werden geprüft. + +--- + +## 2. Dashboard (Widgets) +- Nach der Anmeldung erscheinen die persönlichen **Widgets** (Kennzahlen, Tabellen, Hinweise). +- Widgets werden aus der Datenbank gespeist; welche angezeigt werden, hängt an Ihrem Benutzerkonto. + +--- + +## 3. Serviceaufträge (Requests) +Serviceaufträge kommen aus dem MFR-ERP-System und werden regelmäßig automatisch synchronisiert. + +**Typische Schritte:** +1. **Liste** öffnen (nach Datum oder Suche). +2. Auftrag öffnen → Details, Positionen und ggf. bereits vorhandene Rechnungen ansehen. +3. **Rechnung vorbereiten** (`iget`/`sprep`): Positionen werden in eine Rechnung übernommen und als Vorschau (PDF) angezeigt. +4. Bei Bedarf einzelne Aufträge **aus-/einblenden**. + +--- + +## 4. Rechnungen (Invoices) + +### Erstellen / Bearbeiten +1. Aus einem Serviceauftrag eine Rechnung **vorbereiten** → Vorschau prüfen. +2. **Speichern** (Entwurf) oder weiter **bearbeiten**. Entwürfe tragen ein Wasserzeichen. + +### Finalisieren & Versenden +1. **Bestätigen/Finalisieren**: Die Rechnung erhält eine Rechnungsnummer, das PDF wird erzeugt und gespeichert. +2. Ist eine E-Mail-Adresse hinterlegt, wird die Rechnung **automatisch als PDF-Anhang** per E-Mail versendet. +3. **Erneut senden** ist jederzeit möglich. + +> **Hinweis Versand:** Der E-Mail-/SMS-Versand läuft über die ProcessWeb-Mailer-API +> und ist über `Fuchs:Mailer:Enabled` geschaltet. Ist er deaktiviert, wird der +> Versand nur protokolliert (kein echter Versand). + +### Weitere Aktionen +- **Bezahlt / Unbezahlt** markieren. +- **Storno** oder **Gutschrift** erzeugen (einfach, als Kopie oder als Gutschrift). +- **Zahlungen** und **Positionen** zu einer Rechnung einsehen. +- **Rechnungs-PDF** anzeigen/herunterladen (gespeichertes Dokument oder neu erzeugt). + +### Was steht auf der Rechnung +Das PDF enthält Positionen, Netto/MwSt./Brutto, den **GiroCode (QR zur Überweisung)** +sowie die gesetzlich relevanten Hinweise (u. a. §13b bzw. §35a-Lohnkostenhinweis, +§14-Aufbewahrung, §48-Freistellungsbescheinigung, Steuernummer/USt-ID). + +--- + +## 5. Zahlungserinnerungen (Reminders) +1. Zu einer offenen Rechnung eine **Erinnerung vorbereiten** (Typ/Stufe wählen) → Vorschau. +2. **Finalisieren**: PDF wird erzeugt; bei hinterlegter E-Mail erfolgt der Versand + (Erinnerungs-PDF, ggf. inkl. Rechnungskopie, als Anhang). +3. **Erneut senden** und **Erinnerungen nachschlagen** sind möglich. + +--- + +## 6. Banking (Kontoumsätze) + +### Umsätze importieren +1. Banking → **Kontobericht hochladen**. +2. Datei(en) wählen. Es werden **beide Formate** akzeptiert: + - **MT940** (SWIFT-Text: `.sta`, `.mt940`, `.txt`) + - **CAMT** (ISO 20022 XML: `.xml`, `.camt` — camt.052/053/054) +3. Das System erkennt das Format automatisch, liest die Buchungen ein und führt sie + in die Kontoumsätze über. + +### Umsätze zuordnen +- **Fragliche Überweisungen** anzeigen und prüfen. +- Eine Transaktion einer **Rechnung zuordnen** (`ati`) oder als **erledigt** markieren (`smd`). +- Per Rechnungsnummer nach passenden Rechnungen suchen (`vfi`). + +--- + +## 7. DATEV-Export +- **DATEV-Übersicht** für einen Stichtag/Zeitraum anzeigen (Dateien, Rechnungen). +- **DATEV-ZIP** herunterladen — optional inkl. der Beleg-PDFs. + +--- + +## 8. Berichte (Reports) +1. **Katalog** öffnen — Liste aller verfügbaren Berichte mit Parametern. +2. Bericht auswählen, Parameter setzen, ausführen: + - als **HTML-Seite** (mit optionaler automatischer Aktualisierung), + - als **HTML-Inhalt** (eingebettet), + - oder als **Diagramm (PNG)**. + +--- + +## 9. MFR-Synchronisation (Hintergrund) +- Stammdaten (Firmen, Kontakte, Serviceaufträge, Rechnungen, Belege …) werden vom + **Fuchs_DataService** regelmäßig aus dem MFR-ERP abgeglichen. +- Administrator:innen können eine **Aktualisierung anstoßen** (`mfr_update`) bzw. die + Verknüpfung einzelner Datensätze zurücksetzen. + +--- + +## 10. Hilfe & Support +- Bei Versandproblemen: prüfen, ob der Mailer aktiviert ist und ob eine gültige + E-Mail-/Mobilnummer hinterlegt ist. +- Technische Fehler werden protokolliert (Logging/OpenTelemetry); bitte mit + Uhrzeit und betroffener Aktion an die IT melden: + [info@processweb.de](mailto:info@processweb.de).