Incident Management — Architecture & Data
Incident Management sits on shared Forms, but has its own workflow and boundary.
Overall Architecture
Boundary on FormInstance
Root persistence is FormInstance, but only records with FormCategoryId = IncidentManagement belong to this domain.
| Boundary | Note |
|---|---|
| Owner | IncidentFormInstance aggregate. |
| Scope | Current Business Unit; customer scope through account + acknowledgement. |
| Identity | Incident id and incident guid are used for detail/history/notification. |
| Owned data | Status, incident fields, notification flags, attendee links, acknowledgement links, generated docs. |
| Read dependencies | Org/Site, course, attendance, account, attendee, contact, notification settings. |
Staff/Admin Flow
Customer Flow
Customer does not read incidents directly by attendee. Access goes through FormAcknowledgement:
This rule ensures customers only see incidents/attendees related to the acknowledgement for their current account.
PDF and Attachment
| Component | Role |
|---|---|
IncidentManagementService.GeneratePdfAsync | Builds dataset, calls Reporting service, stores generated document. |
BuildPdfDatasetAsync | Collects incident, attendee, acknowledgement, eligible attachments. |
MergePdfAttachmentsAsync | Appends PDF report with PDF attachments when eligible. |
| Blob service | Stores attachments, generated documents, and signatures. |
Onsite App Webview
Same UI/service, but accessed through the Onsite App wrapper:
- Wrapper passes site identifier(s) and app context; list scope follows that (single-site hides selector, multi-site limits selector).
- Entry "Incident" on the landing page is gated by incident permission.
- Attachment view/download/upload works inside the webview (tablet/mobile), and list/form layout adapts to the viewport.
Description Template Prefill
- Default Description template per incident type is stored in a
form-config-jsonblob (field-prefill format). - Blob name is stored in
FormTemplateVersion.PrefillBlobNameon the active version for the Business Unit; if not set ⇒ use built-in default. - On create/edit, the service materializes Description into plain text, resolving placeholders from current incident data.
Notification Integration
Incidents create notifications at two main points, processed asynchronously:
| Event | When the job is created | What the worker does |
|---|---|---|
IncidentSubmitted | When staff submit an incident. | Resolve staff/manager recipients for the Business Unit, queue one email per recipient with placeholders (incident type, date, time, enterprise/BU/site, attendee names, staff name, admin portal link). Does not create acknowledgement/portal message. |
IncidentSentToCustomer | When staff send an approved incident to customer. | Load incident/contact/template, queue email + SMS based on selected channels, render placeholders; create portal user message if the contact has portal user id. |
- Template fallback: BU has no template configured for the event type ⇒ worker renders from built-in default template instead of skipping/failing the job.
- Unified customer template: one template for Incident/Accident/Illness; the concrete type renders through a placeholder.
- Incident link in customer email points to the customer portal incident list page for the Business Unit.
- After recipient processing completes ⇒ acknowledgement moves to status Sent.
History/Audit
- Lifecycle actions write entity history by incident guid.
- Snapshot is written at major milestones: submit, approve, send to customer, close.
- Staff have a dedicated notification history route to view notification jobs related to an incident.
Next: Codebase flow.