- Updated FdsSqlOptions to accept an optional ILogger parameter for improved error logging. - Modified FdsMfr and FdsMfrClient classes to pass the logger instance to FdsSqlOptions. - Added detailed error logging in various methods to capture SQL execution issues and file handling errors. - Improved documentation for FdsSqlOptions to clarify logging behavior. - Updated Archive class to log compression errors, enhancing traceability of failures. - Adjusted project configuration to suppress specific warnings related to transitive dependencies. - Added NuGet.config to define package sources for dependency management. - Updated submodule references for OCORE and related projects.
3.1 KiB
status, date, applyTo, supersededBy
| status | date | applyTo | supersededBy | |||
|---|---|---|---|---|---|---|
| Accepted | 2026-07-03 |
|
0001 — Domain events (success and failure) trigger user-understandable notifications
Context
Business operations (invoice creation, sending, marking sent, reminders, banking import) happen server-side, often outside a synchronous request the user is watching (background jobs, long-running sends). Users had no reliable way to learn that an operation they cared about — or one that failed — actually happened, short of refreshing lists or checking logs.
Decision
Every meaningful business outcome, success and failure, is modeled as a
DomainEvent (Fuchs/Notifications/DomainEvent.cs) with:
- a
DomainEventTypeenum value identifying what happened, - the acting
UserAccountId, - a
Title, and - a
Contextdictionary of the data needed to render a human-readable message (invoice number, email address, file name, row counts, etc.).
Services call the corresponding method on IEventService
(Fuchs/Notifications/IEventService.cs, implemented by EventService)
at the point the outcome is known — e.g.
InvoiceSentToCustomerAsync(invoice, email, userAccountId) or
InvoiceIssueAsync(message, userAccountId, invoiceId) on failure.
EventService.PublishAsync renders the event into a GuiNotification with a
German, end-user-readable Message (e.g. "Rechnung R2026-0001 wurde an den
Kunden mit der E-Mail test@test.de versandt.") and pushes it — see
0002 for delivery.
Every new business operation with a user-visible outcome (created, sent,
failed, imported, etc.) must add a DomainEventType value and a matching
IEventService method, and call it from the service at the point of success
and the point of failure.
Consequences
IEventServiceis injected into services that perform user-facing operations (InvoiceService,ReminderService,BankingServicecallers) — never bypass it by writing directly toNotificationHub.- Failure paths must call the
*IssueAsync/*Failedevent too, not just succeed-path events — silent failures are the problem this exists to prevent. - Messages are built server-side in
EventService.BuildNotification, in German, using onlyContextvalues — keepContextpopulated with everything the message needs (don't rely on the client to look anything up). - Adding a new event type means updating the enum, the
IEventServiceinterface +EventServiceimplementation (trigger method + message branch +IsFailureif it's a failure type), and the calling service — in the same change.
Alternatives considered
- Polling a status endpoint from the client: rejected — adds latency, extra load, and doesn't generalize to background/multi-tab flows as cleanly as a push model.
- Raw exception messages surfaced to the GUI: rejected — not
user-understandable and leaks internal details;
Context+ a rendered German message keeps the boundary between internal errors and user-facing text explicit.