Files
Fuchs_Intranet/CLAUDE.md
T
Stefan 8a0ebeeb1e Add German localization and styling for administration module
- Introduced new JavaScript file `fis.admin_txt_de.js` for German translations of administration-related terms and messages.
- Created `fis.admin.css` for styling the administration interface, including layout, cards, and buttons.
- Added `fis.admin.de.js` for the main functionality of the administration module, implementing features such as system status checks and email testing.
- Minified version of the German JavaScript file created as `fis.admin.de.min.js`.
- Minified CSS file created as `fis.admin.min.css` for optimized loading.
2026-07-16 14:59:14 +02:00

85 lines
9.0 KiB
Markdown

# CLAUDE.md — Project instructions for Claude Code
> ## ⚠️ Instruction Sync
> This file, **`CODEX.md`**, and **`.github/copilot-instructions.md`** are three
> 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 **all three files in the
> same commit**. This file may add Claude Code / workflow specifics; the shared
> project facts must match `CODEX.md` and `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`). `eRechnungLib` is a submodule (ZUGFeRD/Factur-X + XRechnung generation) — invoices are moving to eRechnung output. `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`.
- Frontend assets are source-built: run the gulp tasks in `Fuchs/` (`npx gulp min`, or `npx gulp all` when copied/static assets also need refreshing) whenever JS or SCSS/CSS sources change. The generated files under `Fuchs/wwwroot/web/` are what the app serves.
- 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 <noreply@anthropic.com>`.
- 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.
- `Fuchs:Email:OverrideRecipient` (`IOptions<FuchsEmailSettings>`, section `Fuchs:Email`) is a dev/test safety net: when non-empty, `ProcessWebComService.SendEmailAsync` discards the real recipient of every outbound email and redirects it to this single address instead, so a locally-enabled mailer can never reach a real tenant-owner or end-customer. Set only in `appsettings.Development.json` — must stay empty in Production.
## 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` (ProcessWeb Mailer API; honors the `Fuchs:Email:OverrideRecipient` dev safety net — see Configuration), `IPdfService`, `IInvoiceService`, `IReminderService`, `IReportService`, `IWidgetService`, `IBankingService`, `IMfrClientFactory`, `ISystemStatusService` (Admin module diagnostics: config snapshot + DB/Key Vault/blob/MFR connectivity probes + test-email; restricted to `fds_sys` > 4). 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).
## MFR ERP integration
- `MFR_RESTClient` is the REST/OData client for the **mfr (Mobile Field Report)** ERP. Its contract (base URLs, auth, OData conventions, pagination, error/retry, deep-create + document-upload) is in **`MFR_RESTClient/Docs/mfr_interface_description.md`** — read it before changing the client.
- HTTP Basic auth; configurable timeout; idempotent GETs retry on transient errors (429/5xx, network/timeout) with backoff. Create clients via `IMfrClientFactory`. Active project is `MFR_RESTClient.csproj` (legacy `.vbproj` removed).
## Database
- Schema source of truth: **`Fuchs_Database`** SSDT project. SQL-first backend (stored procs, table types e.g. `fds__tt__bankingtransactions`, functions via OCORE — no EF Core).
- Changing a proc signature or table type → update the SSDT project **and** the calling C# together; verify every `[dbo].[…]` the backend calls exists in `Fuchs_Database`.
## 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<T>` 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`. Testing must be **extensive**, not superficial:
- For each service/handler change, cover **both** an intentionally succeeding and an intentionally failing path where feasible (stubs/mocks; `InternalsVisibleTo` is enabled).
- Cover edge cases and boundary conditions (empty/null/invalid input, disabled/feature-flag-off states, API/network errors) via `[Theory]`/`[InlineData]`/`[MemberData]` rather than a single happy-path `[Fact]`.
- When behavior depends on configuration (e.g. `appsettings.json` vs `appsettings.Development.json`), prefer loading the **real** files layered the same way ASP.NET Core does (`ConfigurationBuilder` + `AddJsonFile`) over hand-typed literals only, so drift in the actual files is caught (see `ProcessWebComServiceTests.SendEmailAsync_OverrideRecipientFromRealAppsettings_ClearsRecipientWheneverConfigured` for the pattern).
- Assert on the observable contract (e.g. the outgoing request payload) and on emitted telemetry (counters/histograms) when the code records them — not just the boolean return value.
- Name tests `MethodName_Scenario_ExpectedResult`.
- 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`.
## Decisions & Concepts
- `Fuchs/Docs/Decisions/` holds immutable ADRs (architecture decision records); `Fuchs/Docs/Concepts/` holds living design write-ups kept in sync with the code. Each folder's `README.md` explains the format, naming, and required YAML frontmatter — **read it before creating or editing entries there.**
- **Accepted decisions must be followed.** Before working in an area covered by a decision, read it and conform to it; don't silently deviate. Every file's YAML frontmatter has an `applyTo` glob — scan frontmatter across the folder first (cheap) and only read the full body of entries relevant to the files you're touching.
- **Capture new decisions and concepts as they happen.** When a non-obvious architectural or cross-cutting choice gets settled (by the user or in the course of implementation), add a decision in `Docs/Decisions` in the same change, and create/update the matching concept doc in `Docs/Concepts` if the subsystem's design is otherwise non-obvious from the code.
## Documentation map
- `Fuchs/Docs/ARCHITECTURE.md` — solution architecture (keep current when structure changes).
- `Fuchs/Docs/USER_GUIDE.md` — end-user process guide.
- `Fuchs/Docs/Decisions/` — ADRs; see `Decisions & Concepts` above.
- `Fuchs/Docs/Concepts/` — living subsystem design docs; see `Decisions & Concepts` above.
- `MFR_RESTClient/Docs/mfr_interface_description.md` — mfr ERP REST/OData interface contract.
- `.github/instructions/*.instructions.md` — domain-specific contributor guidance.