Behind the scenes (code map)
This guide is written for non-technical readers, but it can be helpful to know “what part of the system does what”.
Core concept: an Occurrence
An “occurrence” is a citizen-reported issue that the municipality manages to completion.
Where it lives:
- Data model: apps/occurrences/models.py → Occurrence
Municipality scoping
Every occurrence is linked to a municipality:
- Occurrence.municipality
The municipality is determined from the submitted location:
- WorkflowPolicyService.determine_municipality_from_location
Configurable workflow (FixMyStreet-style)
Configuration models (all in apps/occurrences/models.py):
- States: OccurrenceState
- Allowed transitions: OccurrenceStateTransition
- Templates: ResponseTemplate
- Auto-response rules: AutoResponseRule
- Priorities/SLAs: PriorityLevel
- Escalations: EscalationRule
- Routing rules: CategoryRouting
- Duplicate policy: DuplicateDetectionSettings
- Duplicate links: OccurrenceLink
- Queued external deliveries (when routing paused): OutboundDelivery
Workflow policy engine (central brain)
Instead of scattering logic across multiple views, the system centralizes “what should happen” here:
- apps/occurrences/services/workflow_policy.py → WorkflowPolicyService
Public submission
Public submission endpoint:
- apps/occurrences/views.py → OccurrenceViewSet.public_submit
Staff actions
Staff actions include:
- Transitioning state: OccurrenceViewSet.transition_state
- Applying templates: ResponseTemplateViewSet endpoints
Asynchronous work (email, routing, escalations)
These run via Celery tasks:
- apps/occurrences/tasks.py
Real-time notifications
WebSocket notifications are emitted via:
- apps/occurrences/websocket_utils.py