-
Notifications
You must be signed in to change notification settings - Fork 0
User Flow Actions
This page provides detailed diagrams for specific user actions within the StateForce platform. These actions represent critical workflows such as creating events, registering institutions, managing resources, handling patients, and more. Each diagram illustrates the steps involved, from user interaction to API calls and database updates, including happy paths and error scenarios, all aligned with the current database schema.
Before diving into the specific action flows, it's important to understand the guiding principles derived from the operational context of StateForce and its Entity-Relationship Diagram (ERD):
-
Central Coordination (
CRUMFocus): Users with roles likeDispatcherorManager(users.role), often operating within acoordination_center(a type ofinstitution), are central to orchestrating emergency responses. Their actions drive event management (eventstable) and resource allocation (resources,event_resources). -
Comprehensive Patient Management: The system features dedicated tables for detailed patient tracking:
-
patients: Core patient information linked to anevent_id. -
patient_vitals: Time-series data for vital signs, recorded by auser_id. -
patient_transfers: Manages the movement of patients between locations, involvingevents,institutions,resources, andusers.
-
-
Detailed Resource Management:
-
resources: Tracks individual resources, theirstatus,available_units,total_units, and association with aninstitution_idandresource_type_id. -
resource_typesandresource_categories: Provide a hierarchical classification for resources.
-
-
Institutional Hierarchy and Specialization:
-
institutions: Can haveparent_institution_idfor hierarchy and adirector_in_charge_id. -
medical_centersandbase_rescues: Specialized institution types with specific attributes (e.g.,level,operating_rooms, coverage) and relationships (e.g.,medical_center_bed_types,medical_center_specialty_types).
-
-
User Roles, Skills, and Associations:
-
user_institutions: Links users to institutions with a specificroleandposition. -
user_skills: Associates users withspecialty_types, including proficiency and expiry. -
user_callsigns: Manages user-specific callsigns within institutions.
-
-
Granular Note-Taking: The
notestable, along with numerous join tables (e.g.,event_notes,patient_notes,institution_notes), allows for contextual note attachment across various entities, withvisibilitycontrols. -
Attachments: The
attachmentstable and its associated join tables (e.g.,event_attachments,resource_attachments) enable file uploads linked to different entities. -
Auditing: The
audit_logstable trackscreated,updated,deletedactions on entities. -
Location Awareness: The
locationstable is central for geolocatinginstitutions,events,resources, etc. -
Contact Management:
contactscan be linked toinstitutions(institution_contacts) andusers(user_contacts), with associatedphone_numbers.
Authorized users (Superadmin, Admin) register new institutions. This flow covers general institutions and specialized types like Medical Centers and Base Rescues, including their specific attributes and related records (e.g., medical_center_bed_types).
This process includes defining core institutional details, location, hierarchy (parent_institution_id), director (director_in_charge_id), and specific attributes if it's a medical_center (e.g., level, operating rooms, initial bed types via medical_center_bed_types) or a base_rescue (e.g., coverage).
Actor: Superadmin or Admin
Preconditions: User is authenticated and authorized. Access to "Institutions Management".
Postconditions:
- New record in
institutions. - If applicable, new record in
medical_centers(and associatedmedical_center_bed_types) orbase_rescues. - Institution linked to
locations. -
audit_logsentry.
- Access Institutions Management, click "Add New Institution."
- System displays form:
- General:
name,callsign,sector_type,description,location_id(select/create),parent_institution_id(optional),director_in_charge_id(optional). - Type Selector: Choose "General", "Medical Center", or "Base Rescue".
- If Medical Center:
level,operating_rooms,internal_pharmacy_available, etc. Section to define initialmedical_center_bed_types(bed_type, total, available). - If Base Rescue: coverage,
triage_status.
- General:
- User fills form. Client-side validation.
- User clicks "Save."
- API Call:
POST /api/institutions(payload includes type and specific fields). - Backend:
- Auth & Authorize.
- Validate data (unique
name,callsignif provided, valid IDs, enum values). - DB Transaction:
- Create
institutionsrecord. - If Medical Center: Create
medical_centersrecord, loop through bed type data to createmedical_center_bed_typesrecords. - If Base Rescue: Create
base_rescuesrecord. - Create
audit_logsentry.
- Create
- Response:
- Success (201): UI success message, update list.
- Error (422, 409, 400): UI shows specific errors (e.g., "Callsign already in use," "Invalid parent institution," "Bed type configuration error").
flowchart TD
A["Start: User accesses Institutions Management"] --> B["User clicks 'Add New Institution'"];
B --> C["System displays 'Create Institution' form with type selector (General, Medical Center, Base Rescue)"];
C --> D["User selects type and fills details (name, callsign, location, parent_id, director_id, type-specific fields like beds for MC)"];
D --> E{"Client-Side Validation"};
E -- Invalid --> F["UI: Highlight errors"];
F --> D;
E -- Valid --> G["User clicks 'Save'"];
G --> H["API Call: POST /api/institutions with all data"];
H --> I["Backend: Authenticate & Authorize"];
I -- Unauthorized --> I_Err["API 403"];
I_Err --> I_Msg["UI: Permission Denied"];
I_Msg --> C;
I -- Authorized --> J{"Backend: Validate General & Type-Specific Data (unique name, callsign, valid IDs, bed config for MC)"};
J -- Invalid --> K["API 422/400/409 (e.g., 'Callsign exists', 'Invalid bed count')"];
K --> L["UI: Display specific errors on form"];
L --> D;
J -- Valid --> M["Backend: DB Transaction Start"];
M --> N["Create 'institutions' record"];
N --> O{Is it a Medical Center?};
O -- Yes --> P["Create 'medical_centers' record"];
P --> P1["Create 'medical_center_bed_types' records"];
P1 --> Q;
O -- No --> O1{Is it a Base Rescue?};
O1 -- Yes --> R["Create 'base_rescues' record"];
R --> Q;
O1 -- No --> Q;
Q["Backend: Create 'audit_logs' entry"] --> S["Backend: DB Transaction Commit"];
S -- Success --> T["API responds 201 Created"];
T --> U["UI: Success message, new institution in list"];
U --> Z["End"];
S -- DB Error --> S_Err["API 500"];
S_Err --> S_Msg["UI: Unexpected error"];
S_Msg --> G;
Dispatchers or Managers create new events based on incoming reports. This involves capturing essential details, location, priority, and an optional unique event_code.
(Largely similar to previous, but emphasizing event_code and schema fields)
Actor: Dispatcher or Manager
Preconditions: Authenticated, authorized. External report received.
Postconditions:
- New
eventsrecord. - Visible on Event Dashboard.
-
audit_logsentry.
- Receive report, navigate to "Create New Event."
- Form displayed:
event_type,location_id,reported_time,description,priority_level,triage_status,people_affected,reported_by_text,event_code(optional, system may suggest/validate uniqueness). - Fill form. Client-side validation.
- Submit.
- API Call:
POST /api/events. - Backend:
- Auth & Authorize.
- Validate (valid
location_id, enums, uniqueevent_codeif provided and required to be unique). - Create
eventsrecord. - Create
audit_logsentry.
- Response: Success (201) or Error (422 for validation, 409 for duplicate
event_code).
flowchart TD
A["Start: Dispatcher receives report"] --> B["Navigates to Event Dashboard, clicks 'Create New Event'"];
B --> C["System displays 'Create Event' form"];
C --> D["Dispatcher fills details (type, location, priority, description, event_code, etc.)"];
D --> E{"Client-Side Validation"};
E -- Invalid --> F["UI: Highlight errors"];
F --> D;
E -- Valid --> G["User clicks 'Create Event'"];
G --> H["API Call: POST /api/events"];
H --> I["Backend: Authenticate & Authorize"];
I -- Unauthorized --> I_Err["API 403"];
I_Err --> I_Msg["UI: Permission Denied"];
I_Msg --> C;
I -- Authorized --> J{"Backend: Validate Data (location_id, enums, unique event_code if provided)"};
J -- "Invalid (e.g., location not found, event_code duplicate)" --> K["API 422/400/409"];
K --> L["UI: Display specific errors (e.g., 'Event Code already exists')"];
L --> D;
J -- Valid --> M["Backend: Create 'events' record"];
M --> N["Backend: Create 'audit_logs' entry"];
N -- Success --> O["API responds 201 Created"];
O --> P["UI: Success, new event on dashboard/details page"];
P --> Z["End"];
N -- DB Error --> N_Err["API 500"];
N_Err --> N_Msg["UI: Unexpected error"];
N_Msg --> G;
Admins or Managers manage the lifecycle of resources, including creating new resource types, categories, and individual resource instances.
This involves:
-
A. Managing Resource Categories: CRUD for
resource_categories(e.g., Vehicles, Equipment, Personnel Types). -
B. Managing Resource Types: CRUD for
resource_types(e.g., Ambulance, Fire Truck, Paramedic), linking them to aresource_category_id. -
C. Managing Resources: CRUD for
resourcesinstances (e.g., Ambulance A-101). This includesname,description,total_units,available_units,status,institution_id,resource_type_id,location_id(optional),icon_id(optional).
Actor: Admin or Manager (with appropriate permissions)
Preconditions: User authenticated and authorized.
Postconditions: Records created/updated/deleted in resource_categories, resource_types, resources. audit_logs entries.
flowchart TD
subgraph ManageResourceCategoriesAndTypes ["Separate Flows: Manage Resource Categories & Types (Simpler CRUD)"]
direction LR
RC1["Admin accesses Resource Categories/Types UI"] --> RC2["Performs CRUD operations (Create, Read, Update, Delete)"]
RC2 --> RC3["API calls like POST/GET/PUT/DELETE /api/resource-categories or /api/resource-types"]
RC3 --> RC4["Backend validates, updates DB, logs audit"]
RC4 --> RC5["UI reflects changes"]
end
A["Start: User accesses Resource Management (Instances)"] --> B{"Choose Action: Create/Update/View Resource"};
B -- "Create New Resource" --> C_New["User clicks 'Add New Resource'"];
C_New --> C_Form["UI: Displays 'Create Resource' form (name, desc, total_units, institution_id, resource_type_id, location_id, icon_id, status)"];
C_Form --> C_Fill["User fills form"];
C_Fill --> C_Validate{"Client-Side Validation"};
C_Validate -- Invalid --> C_Err_UI["UI: Highlight errors"];
C_Err_UI --> C_Fill;
C_Validate -- Valid --> C_Save["User clicks 'Save'"];
C_Save --> C_API["API: POST /api/resources"];
C_API --> C_Backend{"Backend: Auth, Validate (IDs exist, units logic), Create 'resources' record, Log 'audit_logs'"};
C_Backend -- Success --> C_Success["API 201, UI: Success, resource in list"];
C_Success --> A;
C_Backend -- "Validation Error (e.g., type_id invalid, institution_id invalid)" --> C_Err_Val["API 422/400"];
C_Err_Val --> C_Msg_Val["UI: Specific error on form"];
C_Msg_Val --> C_Fill;
C_Backend -- "Server Error" --> C_Err_Server["API 500, UI: Generic error"];
C_Err_Server --> C_Save;
B -- "Update Existing Resource" --> U_Select["User selects resource, clicks 'Edit'"];
U_Select --> U_Form["UI: Displays 'Edit Resource' form (pre-filled)"];
U_Form --> U_Fill["User modifies form"];
U_Fill --> U_Validate{"Client-Side Validation"};
U_Validate -- Invalid --> U_Err_UI["UI: Highlight errors"];
U_Err_UI --> U_Fill;
U_Validate -- Valid --> U_Save["User clicks 'Update'"];
U_Save --> U_API["API: PUT /api/resources/{id}"];
U_API --> U_Backend{"Backend: Auth, Validate, Update 'resources' record, Log 'audit_logs'"};
U_Backend -- Success --> U_Success["API 200, UI: Success, list updated"];
U_Success --> A;
U_Backend -- "Error" --> U_Err_Server["API 422/400/404/500, UI: Error message"];
U_Err_Server --> U_Fill;
B -- "View Resource Details" --> V_Details["UI: Displays resource details"];
V_Details --> A;
Dispatchers or Managers assign institutions (event_institutions) and resources (event_resources) to an active event. This includes specifying quantity_assigned for resources and noting the assigned_by_user_id.
(Largely similar to previous, but with schema-specific fields like assigned_by_user_id and quantity_assigned)
Actor: Dispatcher or Manager
Preconditions: Event exists. User authenticated. Available institutions/resources.
Postconditions: Records in event_institutions / event_resources. resources.available_units updated. audit_logs.
flowchart TD
A["Start: User on Event Detail page (Event ID: {id})"] --> B{"Choose Action"};
B -- "Assign Institutions" --> B1_Init["User clicks 'Assign Institution'"];
B1_Init --> B1_Select["UI: Select Institutions"];
B1_Select --> B1_Confirm["User confirms"];
B1_Confirm --> B1_APICall["API: POST /api/events/{id}/institutions"];
B1_APICall --> B1_Backend{"Backend: Auth, Validate, Create 'event_institutions' (event_id, institution_id, assigned_at), Log 'audit_logs'"};
B1_Backend -- Success --> B1_UIUpdate["UI: Success, list updated"];
B1_UIUpdate --> B;
B1_Backend -- "Error (e.g., already assigned, institution invalid)" --> B1_Error["API 4xx/500, UI: Error message"];
B1_Error --> B1_Select;
B -- "Assign Resources" --> B2_Init["User clicks 'Assign Resource'"];
B2_Init --> B2_Select["UI: Select Resources & Specify 'quantity_assigned'"];
B2_Select --> B2_Confirm["User confirms"];
B2_Confirm --> B2_APICall["API: POST /api/events/{id}/resources"];
B2_APICall --> B2_Backend{"Backend: Auth, Validate (resource available, quantity <= available_units), Create 'event_resources' (event_id, resource_id, quantity_assigned, assigned_by_user_id, assigned_at), Update 'resources.available_units', Log 'audit_logs'"};
B2_Backend -- Success --> B2_UIUpdate["UI: Success, list updated, resource availability reflects change"];
B2_UIUpdate --> B;
B2_Backend -- "Error (e.g., resource unavailable, insufficient units)" --> B2_Error["API 4xx/500, UI: Error message"];
B2_Error --> B2_Select;
B -- "Update Event Status" --> B3_Init["User clicks 'Update Status'"];
B3_Init --> B3_Select["UI: Select new EventStatus"];
B3_Select --> B3_Confirm["User confirms"];
B3_Confirm --> B3_APICall["API: PUT /api/events/{id} with new status"];
B3_APICall --> B3_Backend{"Backend: Auth, Validate, Update 'events.status', Log 'audit_logs'"};
B3_Backend -- Success --> B3_UIUpdate["UI: Success, status updated"];
B3_UIUpdate --> B;
B3_Backend -- "Error" --> B3_Error["API 4xx/500, UI: Error message"];
B3_Error --> B3_Select;
B -- "View Details Only" --> Z["End / Continue Monitoring"];
Field personnel or dispatchers register patients associated with an event, capturing basic demographic data and initial triage status.
When individuals are identified at an event scene, their details are logged into the patients table, linked directly to the event_id.
Actor: Paramedic (Standard User), Dispatcher, Manager
Preconditions:
- An active
eventexists. - User is authenticated and authorized.
- Patient information is available. Postconditions:
- A new record is created in the
patientstable, linked to theevent_id. -
audit_logsentry.
- User is on the Event Detail page or a dedicated "Add Patient to Event" interface.
- User clicks "Add Patient."
- System displays form for
patientstable:name,age,gender,triage_status.event_idis pre-filled or selected. - User fills form. Client-side validation.
- User clicks "Save Patient."
- API Call:
POST /api/events/{event_id}/patientsorPOST /api/patients(withevent_idin payload). - Backend Processing:
- Authenticate & Authorize.
- Validate data (e.g.,
agerange, validevent_id, enums). - Create new record in
patientstable. - Create
audit_logsentry.
- Handle Backend Response:
- Success (201): UI displays success, patient appears in event's patient list.
- Error (422, 400, 404): UI displays specific errors.
flowchart TD
A["Start: User on Event Detail page (Event ID: {id})"] --> B["User clicks 'Add Patient'"];
B --> C["System displays 'Register Patient' form (name, age, gender, triage_status) with Event ID {id} pre-filled"];
C --> D["User fills patient details"];
D --> E{"Client-Side Validation (e.g., age 0-125)"};
E -- Invalid --> F["UI: Highlight errors on form"];
F --> D;
E -- Valid --> G["User clicks 'Save Patient'"];
G --> H["API Call: POST /api/events/{id}/patients with patient data"];
H --> I["Backend: Authenticate & Authorize User"];
I -- Unauthorized --> I_Err["API 403"];
I_Err --> I_Msg["UI: Permission Denied"];
I_Msg --> C;
I -- Authorized --> J{"Backend: Server-Side Validation (event_id exists, age range, enums)"};
J -- Invalid --> K["API responds 422/400/404 with error details"];
K --> L["UI: Displays specific errors on form (e.g., 'Event not found', 'Age must be between 0 and 125')"];
L --> D;
J -- Valid --> M["Backend: Create record in 'patients' table (linked to event_id)"];
M --> N["Backend: Create record in 'audit_logs' table"];
N -- Success --> O["API responds 201 Created"];
O --> P["UI: Displays 'Success! Patient registered.' Patient appears in event's patient list."];
P --> A;
N -- DB Error --> N_Err["API 500"];
N_Err --> N_Msg["UI: Unexpected error registering patient."];
N_Msg --> G;
Authorized medical personnel record vital signs for a registered patient at various intervals.
This involves selecting a patient (already linked to an event) and submitting a set of vital signs which are stored in the patient_vitals table, including recorded_at and recorded_by_user_id.
Actor: Paramedic (Standard User), Nurse, Doctor
Preconditions:
- Patient exists in
patientstable and is associated with an event. - User is authenticated and authorized to record vitals. Postconditions:
- New record(s) in
patient_vitalstable, linked topatient_idandrecorded_by_user_id. -
audit_logsentry.
- User navigates to Patient's Detail page (which shows current event context).
- User clicks "Record Vitals."
- System displays form for
patient_vitals:blood_pressure_systolic,blood_pressure_diastolic,heart_rate,oxygen_saturation,respiratory_rate,temperature,capillary_blood_glucose,glasgow_coma_scale.recorded_atdefaults to now.patient_idis context,recorded_by_user_idis current user. - User fills form. Client-side validation.
- User clicks "Save Vitals."
- API Call:
POST /api/patients/{patient_id}/vitals. - Backend:
- Auth & Authorize.
- Validate data (numeric ranges,
patient_idexists). - Create
patient_vitalsrecord. - Create
audit_logsentry.
- Response: Success (201), UI shows new vitals entry in patient's history. Error (422, 404).
flowchart TD
A["Start: User on Patient Detail page (Patient ID: {pid})"] --> B["User clicks 'Record Vitals'"];
B --> C["System displays 'Record Vitals' form (BP, HR, SpO2, Temp, etc.)"];
C --> D["User enters vital signs data"];
D --> E{"Client-Side Validation (e.g., numeric, within reasonable physiological ranges if defined)"};
E -- Invalid --> F["UI: Highlight errors"];
F --> D;
E -- Valid --> G["User clicks 'Save Vitals'"];
G --> H["API Call: POST /api/patients/{pid}/vitals with vitals data"];
H --> I["Backend: Authenticate & Authorize User"];
I -- Unauthorized --> I_Err["API 403"];
I_Err --> I_Msg["UI: Permission Denied"];
I_Msg --> C;
I -- Authorized --> J{"Backend: Server-Side Validation (patient_id exists, data types/ranges)"};
J -- Invalid --> K["API responds 422/404 with error details"];
K --> L["UI: Displays specific errors (e.g., 'Patient not found', 'Invalid temperature value')"];
L --> D;
J -- Valid --> M["Backend: Create record in 'patient_vitals' (linked to patient_id, recorded_by_user_id, recorded_at)"];
M --> N["Backend: Create record in 'audit_logs' table"];
N -- Success --> O["API responds 201 Created"];
O --> P["UI: Displays 'Success! Vitals recorded.' Vitals appear in patient's timeline."];
P --> A;
N -- DB Error --> N_Err["API 500"];
N_Err --> N_Msg["UI: Unexpected error saving vitals."];
N_Msg --> G;
This complex flow covers requesting a patient transfer from an event scene or one facility to another, assigning transport, and tracking its status. It involves patient_transfers, patients, events, institutions (destination), resources (transport), and users (requesting, accepting).
A requesting_user_id initiates a transfer for a patient_id (linked to an event_id) to a destination_institution_id, assigning a transport_resource_id. An accepted_by_user_id (likely at the destination or CRUM) confirms. Status updates track progress.
Actor: Dispatcher, Paramedic, Manager
Preconditions: Patient registered. Event active. Destination and transport resource identified.
Postconditions:
-
patient_transfersrecord created/updated. -
resources.statusof transport may change. -
audit_logsentries.
- Initiate Transfer: On Patient Detail or Event page, user clicks "Request Patient Transfer."
-
Fill Transfer Form:
-
patient_id(context). -
event_id(context). -
destination_institution_id(selectable list of medical centers). -
transport_resource_id(selectable list of available, suitable resources like ambulances). -
requesting_user_id(current user).
-
- Submit Request:
- API Call:
POST /api/patient-transfers. - Backend:
- Auth & Authorize.
- Validate (all IDs exist, patient part of event, institution is medical center, resource is transport type and available).
- Create
patient_transfersrecord withstatus: 'pending'. - Notify relevant parties (e.g., destination institution, CRUM).
- Log in
audit_logs.
-
Accept/Manage Transfer:
- Authorized user (e.g., at destination or CRUM) views pending transfers.
- Selects transfer, clicks "Accept Transfer."
- API Call:
PUT /api/patient-transfers/{transfer_id}/accept(or similar). - Backend: Update
patient_transfers.statustoaccepted(or other relevant status likeen_routeonce transport departs), setaccepted_by_user_id. Updatetransport_resource_id.statustoassigned. Log.
-
Update Progress:
-
departure_timelogged when transport leaves. -
arrival_timelogged when patient arrives at destination. -
statusupdated todoneorcancelled.
-
flowchart TD
subgraph RequestTransfer [Phase 1: Requesting Transfer]
direction LR
RT1["User on Patient/Event page, clicks 'Request Transfer' for Patient {pid}"] --> RT2["UI: Form (Destination Institution, Transport Resource)"];
RT2 --> RT3["User selects Destination & Transport, clicks 'Submit Request'"];
RT3 --> RT4["API: POST /api/patient-transfers (patient_id, event_id, dest_inst_id, transport_res_id, requesting_user_id)"];
RT4 --> RT5{"Backend: Auth, Validate (IDs, resource availability/suitability, institution capacity/type)"};
RT5 -- Invalid --> RT5_Err["API 4xx, UI: Error (e.g., 'Transport unavailable', 'Destination at capacity')"];
RT5_Err --> RT2;
RT5 -- Valid --> RT6["Backend: Create 'patient_transfers' (status 'pending'), Log audit"];
RT6 -- Success --> RT7["API 201, UI: 'Transfer Requested', Notify relevant parties"];
end
subgraph ManageTransfer [Phase 2: Managing Transfer 'e.g., by CRUM or Destination']
direction LR
MT1["User CRUM/Destination views pending transfers"] --> MT2["Selects transfer, clicks 'Accept Transfer'"];
MT2 --> MT3["API: PUT /api/patient-transfers/'id'/accept (sets accepted_by_user_id)"];
MT3 --> MT4{"Backend: Auth, Validate, Update 'patient_transfers.status' to 'accepted', Update 'resources.status' for transport, Log audit"};
MT4 -- Success --> MT5["API 200, UI: 'Transfer Accepted'"];
MT5 --> MT_UpdateLoop;
MT_UpdateLoop["Ongoing: Update Transfer Status/Times"];
MT_UpdateLoop -- "Transport Departs" --> MT_Depart["Log 'departure_time', status 'en_route' via API PUT /api/patient-transfers/{id}"];
MT_Depart --> MT_UpdateLoop;
MT_UpdateLoop -- "Patient Arrives" --> MT_Arrive["Log 'arrival_time', status 'arrived' via API"];
MT_Arrive --> MT_UpdateLoop;
MT_UpdateLoop -- "Transfer Complete" --> MT_Done["Update status 'done' via API"];
MT_Done --> Z_EndTransfer["End Transfer"];
MT_UpdateLoop -- "Cancel Transfer" --> MT_Cancel["Update status 'cancelled' via API"];
MT_Cancel --> Z_EndTransfer;
end
RT7 --> MT1;
Admin/Superadmin invites new users via email. The invitee uses a token to register, being automatically linked to an institution_id with a specified role and position in user_institutions.
(Largely similar to previous, but ensuring user_institutions.position and user_institutions.status are handled)
Actor: Admin/Superadmin (inviter), New User (invitee)
Preconditions: Admin authenticated.
Postconditions: invites record used. New users record. New user_institutions record (with role, position, status 'accepted' or 'active'). audit_logs.
flowchart TD
subgraph Admin_Flow [Admin Sends Invitation]
direction LR
A1["Start: Admin in User Management"] --> A2["Clicks 'Invite New User'"];
A2 --> A3["Fills form (email, institution_id, role, position)"];
A3 --> A4["Clicks 'Send Invite'"];
A4 --> A5["API: POST /api/invites"];
A5 --> A6{"Backend: Auth, Validate, Gen Token, Create 'invites' (status 'sent', inviter_id, institution_id, role), Send Email, Log audit"};
A6 -- Success --> A7["UI: Success message"];
A6 -- "Error (e.g., email exists, invalid inst_id)" --> A8["API 4xx, UI: Error message"];
A8 --> A3;
end
subgraph User_Flow [New User Accepts & Registers]
direction LR
U1["Invitee receives email, clicks token link"] --> U2["Registration page with token"];
U2 --> U3["Fills form (name, password, user_callsign - optional)"];
U3 --> U4["Clicks 'Create Account'"];
U4 --> U5["API: POST /api/users/register (form data & token)"];
U5 --> U6{"Backend: Validate token (exists, not expired, 'sent')"};
U6 -- "Invalid Token" --> U6_Err["API 400/410, UI: 'Token invalid/expired'"];
U6_Err --> U2;
U6 -- "Valid Token" --> U7{"Backend: Validate input, Create 'users' record (set confirmed_at)"};
U7 --> U8{"Backend: Create 'user_institutions' (user_id, institution_id from invite, role from invite, position from invite, status 'active')"};
U8 --> U8a{"(Optional) Backend: If callsign provided, create 'user_callsigns' record"};
U8a --> U9["Backend: Update 'invites' (status 'accepted', used_at), Log audit"];
U9 -- Success --> U10["API 201, UI: Success, User logged in, Redirect to dashboard"];
U7 -- "Error creating user" --> U_Err_Create["API 422/500, UI: Error"];
U_Err_Create --> U3;
end
A7 --> U1;
Admins manage user access by modifying their role and position within user_institutions. They also manage user_skills by linking users to specialty_types.
-
A. Role/Position Management: Update
user_institutions.roleoruser_institutions.position. -
B. Skill Management: Add/remove
specialty_typesfor a user viauser_skills, specifyingskill_proficiency_levelandexpiry_date.
Actor: Admin or Superadmin
Preconditions: User exists. Admin authorized.
Postconditions: user_institutions or user_skills updated. audit_logs.
flowchart TD
A["Start: Admin on User Profile page"] --> B{"Choose Action: Manage Roles/Positions OR Manage Skills"};
B -- "Manage Roles/Positions" --> C1["Admin selects an institution link from 'user_institutions' list"];
C1 --> C2["Clicks 'Edit Role/Position'"];
C2 --> C3["UI: Form to change 'role' (enum) and 'position' (text) for that user_institution entry"];
C3 --> C4["Admin makes changes, clicks 'Save'"];
C4 --> C5["API: PUT /api/user-institutions/{user_id}/{institution_id} (or dedicated PK if exists) with new role/position"];
C5 --> C6{"Backend: Auth, Validate, Update 'user_institutions', Log audit"};
C6 -- Success --> C7["API 200, UI: Success, profile updated"];
C7 --> A;
C6 -- "Error" --> C_Err["API 4xx/500, UI: Error"];
C_Err --> C3;
B -- "Manage Skills" --> D1["Admin clicks 'Manage Skills'"];
D1 --> D2["UI: Shows current skills from 'user_skills', option to 'Add Skill'"];
D2 --> D3{"Action: Add or Remove Skill?"};
D3 -- "Add Skill" --> D_Add1["UI: Select 'specialty_type_id', set 'skill_proficiency_level', 'expiry_date' (optional)"];
D_Add1 --> D_Add2["Admin clicks 'Add'"];
D_Add2 --> D_Add_API["API: POST /api/users/{user_id}/skills"];
D_Add_API --> D_Add_Backend{"Backend: Auth, Validate (specialty_id exists), Create 'user_skills' record, Log audit"};
D_Add_Backend -- Success --> D_Add_Success["API 201, UI: Skill added to list"];
D_Add_Success --> D2;
D_Add_Backend -- "Error" --> D_Add_Err["API 4xx/500, UI: Error"];
D_Add_Err --> D_Add1;
D3 -- "Remove Skill" --> D_Remove1["User selects a skill, clicks 'Remove'"];
D_Remove1 --> D_Remove_API["API: DELETE /api/users/{user_id}/skills/{skill_id}"];
D_Remove_API --> D_Remove_Backend{"Backend: Auth, Delete 'user_skills' record, Log audit"};
D_Remove_Backend -- Success --> D_Remove_Success["API 200/204, UI: Skill removed"];
D_Remove_Success --> D2;
D_Remove_Backend -- "Error" --> D_Remove_Err["API 4xx/500, UI: Error"];
D_Remove_Err --> D_Remove1;
Create contacts, then link them to institutions (via institution_contacts with contact_type) or users (via user_contacts with contact_type). Manage phone_numbers for contacts via contact_phone_numbers.
(Similar to previous, but explicitly includes user_contacts and detailed phone number management)
flowchart TD
subgraph CreateContact [Part 1: Create Generic Contact]
direction LR
CC1["User in Contacts Directory"] --> CC2["Clicks 'Create New Contact'"];
CC2 --> CC3["Fills form (name, email, radio_freq)"];
CC3 --> CC4["Clicks 'Save Contact'"];
CC4 --> CC5["API: POST /api/contacts"];
CC5 --> CC6{"Backend: Auth, Validate (unique email), Create 'contacts', Log audit"};
CC6 -- Success --> CC7["UI: Success, Contact in directory"];
CC6 -- "Error (e.g., email exists)" --> CC8["API 4xx, UI: Error"];
CC8 --> CC3;
end
subgraph LinkContactToEntity [Part 2: Link Contact to Institution or User]
direction LR
LC1["User on Contact/Institution/User Profile"] --> LC2{"Link to Institution or User?"};
LC2 -- Institution --> LC_Inst1["Clicks 'Link to Institution'"];
LC_Inst1 --> LC_Inst2["UI: Select Institution, ContactType"];
LC_Inst2 --> LC_Inst3["Confirm"];
LC_Inst3 --> LC_Inst_API["API: POST /api/institution-contacts (contact_id, institution_id, contact_type)"];
LC_Inst_API --> LC_Inst_Backend{"Backend: Auth, Validate, Create 'institution_contacts', Log audit"};
LC_Inst_Backend -- Success --> LC_Inst_Success["UI: Success"];
LC_Inst_Backend -- "Error (e.g., link exists)" --> LC_Inst_Err["API 4xx, UI: Error"];
LC2 -- User --> LC_User1["Clicks 'Link to User'"];
LC_User1 --> LC_User2["UI: Select User, ContactType"];
LC_User2 --> LC_User3["Confirm"];
LC_User3 --> LC_User_API["API: POST /api/user-contacts (contact_id, user_id, contact_type)"];
LC_User_API --> LC_User_Backend{"Backend: Auth, Validate, Create 'user_contacts', Log audit"};
LC_User_Backend -- Success --> LC_User_Success["UI: Success"];
LC_User_Backend -- "Error" --> LC_User_Err["API 4xx, UI: Error"];
end
subgraph ManagePhoneNumbers [Part 3: Manage Phone Numbers for a Contact]
direction LR
PN1["User on Contact Profile, views Phone Numbers section"] --> PN2{"Add/Edit/Delete Phone?"};
PN2 -- Add --> PN_Add1["Clicks 'Add Phone'"];
PN_Add1 --> PN_Add2["UI: Form for 'phone_numbers' (number, type, ext), 'is_primary' for 'contact_phone_numbers'"];
PN_Add2 --> PN_Add3["Confirm"];
PN_Add3 --> PN_Add_API["API: POST /api/contacts/{contact_id}/phones"];
PN_Add_API --> PN_Add_Backend{"Backend: Auth, Validate, Create 'phone_numbers', Create 'contact_phone_numbers', Log audit"};
PN_Add_Backend -- Success --> PN_Add_Success["UI: Phone added"];
PN_Add_Backend -- "Error" --> PN_Add_Err["API 4xx, UI: Error"];
end
CC7 --> LC1;
CC7 --> PN1;
Users create notes and can associate them with various entities like events (via event_notes), users (via user_notes), institutions (via institution_notes), patients (via patients_notes), etc. Notes have title, body, visibility, and a creator_user_id. note_editors tracks who edited a note.
This flow focuses on creating a note and linking it to one primary entity. Viewing/editing notes would be similar.
Actor: Any authorized user
Preconditions: User authenticated. Context entity (e.g., Event, Patient) exists.
Postconditions: notes record created. Join table record (e.g., event_notes) created. audit_logs.
- User is viewing an entity (e.g., Event Detail page).
- User clicks "Add Note."
- UI: Form for
notes(title,body,visibility).creator_user_idis current user. - User fills form, clicks "Save Note."
- API Call: e.g.,
POST /api/events/{event_id}/notes(or generic/api/noteswith entity link in payload). - Backend:
- Auth & Authorize.
- Validate data.
- DB Transaction:
- Create
notesrecord. - Create corresponding join table record (e.g.,
event_noteslinkingevent_idand newnote_id). - (Implicitly)
note_editorsmight get an initial entry if creator is considered first editor. - Log in
audit_logs.
- Create
- Response: Success (201), UI shows note. Error (4xx).
flowchart TD
A["Start: User on an entity page (e.g., Event ID: {eid}, Patient ID: {pid})"] --> B["User clicks 'Add Note' to this entity"];
B --> C["UI: Displays 'Create Note' form (title, body, visibility)"];
C --> D["User fills note details"];
D --> E{"Client-Side Validation"};
E -- Invalid --> F["UI: Highlight errors"];
F --> D;
E -- Valid --> G["User clicks 'Save Note'"];
G --> H["API Call: POST /api/{entity_type}/{entity_id}/notes (e.g., /api/events/{eid}/notes)"];
H --> I["Backend: Authenticate & Authorize User for entity"];
I -- Unauthorized --> I_Err["API 403, UI: Permission Denied"];
I_Err --> C;
I -- Authorized --> J{"Backend: Validate Note Data (title/body not empty, valid visibility)"};
J -- Invalid --> K["API 422, UI: Specific errors on form"];
K --> D;
J -- Valid --> L["Backend: DB Transaction Start"];
L --> M["Create 'notes' record (creator_user_id = current user)"];
M --> N["Create join table record (e.g., 'event_notes' linking note_id to {eid})"];
N --> O["(Optional) Create 'note_editors' record for creator"];
O --> P["Create 'audit_logs' entry for note creation"];
P --> Q["Backend: DB Transaction Commit"];
Q -- Success --> R["API responds 201 Created"];
R --> S["UI: Displays 'Success! Note added.' Note appears in entity's notes list."];
S --> A;
Q -- DB Error --> Q_Err["API 500, UI: Unexpected error saving note."];
Q_Err --> G;
Dispatchers or field units log significant updates, decisions, or communications related to an active event. This uses the event_notes system, where a note is created and linked to the event_id.
This is a specialized use of the "Managing Notes" flow, specifically for events. The note.body would contain the communication summary or update. note.title could be a timestamp or brief subject.
Actor: Dispatcher, Paramedic, Manager
Preconditions: Active event. User authenticated.
Postconditions: New notes record. New event_notes record. audit_logs.
flowchart TD
A["Start: User on Event Detail page (Event ID: {eid}), communication/update occurs"] --> B["User clicks 'Log Update/Communication' (or 'Add Event Note')"];
B --> C["UI: Displays 'New Event Note/Log' form (title - e.g., 'Radio Comms @10:30', body - details, visibility)"];
C --> D["User fills log details"];
D --> E{"Client-Side Validation"};
E -- Invalid --> F["UI: Highlight errors"];
F --> D;
E -- Valid --> G["User clicks 'Save Log'"];
G --> H["API Call: POST /api/events/{eid}/notes with note data"];
H --> I["Backend: Authenticate & Authorize User for event"];
I -- Unauthorized --> I_Err["API 403, UI: Permission Denied"];
I_Err --> C;
I -- Authorized --> J{"Backend: Validate Note Data"};
J -- Invalid --> K["API 422, UI: Specific errors"];
K --> D;
J -- Valid --> L["Backend: DB Transaction Start"];
L --> M["Create 'notes' record (creator_user_id = current user)"];
M --> N["Create 'event_notes' record (linking note_id to {eid})"];
N --> O["Create 'audit_logs' entry"];
O --> P["Backend: DB Transaction Commit"];
P -- Success --> Q["API responds 201 Created"];
Q --> R["UI: Displays 'Log saved.' Update appears in event's timeline/notes."];
R --> A;
P -- DB Error --> P_Err["API 500, UI: Unexpected error."];
P_Err --> G;
Users upload files (attachments table) and associate them with various entities via join tables (e.g., event_attachments, institution_attachments, resource_attachments, medical_center_attachments, base_rescue_attachments).
(Similar to previous, but acknowledging the various join tables based on context)
sequenceDiagram
participant User
participant UI
participant API
participant FileStorage
participant DB
User->>UI: On Entity Page (e.g., Event, Institution), Click 'Attach File'
UI->>User: Display File Upload Dialog
User->>UI: Select file, add description, visibility, Click 'Upload'
UI->>API: POST /api/attachments (multipart/form-data with file, metadata, and entity_type, entity_id for linking)
API->>DB: Authenticate & Authorize User for entity
alt Auth Fails
API->>UI: Respond 403 Forbidden
end
API->>FileStorage: Server-Side File Validation (type, size) & Store file
alt File Validation/Storage Fails
FileStorage-->>API: Error (e.g., too large, type not allowed, storage error)
API->>UI: Respond 400/413/500
else File OK
FileStorage->>API: Return file_url
end
API->>DB: Validate metadata
alt Metadata Invalid
API->>UI: Respond 422
end
API->>DB: DB Transaction Start
API->>DB: Create 'attachments' record (uploader_user_id, file_url, file_name, etc.)
API->>DB: Based on entity_type, create join table record (e.g., 'event_attachments' linking event_id and new attachment_id)
API->>DB: Log in 'audit_logs'
alt DB Operation Fails
API->>DB: Rollback Transaction
API->>UI: Respond 500
else Success
DB->>API: Commit Transaction, Records created
API->>UI: Success response (201 Created) with attachment details
UI->>User: Display 'Success', Attachment listed
end
Authorized users schedule calendar_entries (meetings, training), linking them to institutions (via calendar_entries_institutions) and optionally to an event_id.
(Similar to previous, ensuring calendar_entries_institutions is handled)
sequenceDiagram
participant Manager
participant UI
participant API
participant DB
Manager->>UI: Navigate to Calendar, Click 'Create Calendar Entry'
UI->>Manager: Display form (title, desc, scheduled_at, ends_at/duration, recurrence, priority, visibility, associated institution_ids, optional event_id)
Manager->>UI: Fill form, Click 'Save'
UI->>API: POST /api/calendar-entries with data
API->>DB: Auth & Validate (data types, institution_ids exist, event_id exists if provided)
alt Validation Fails
API->>UI: Respond 4xx (e.g., 422, 400)
end
API->>DB: DB Transaction Start
API->>DB: Create 'calendar_entries' record (creator_user_id, event_id if present)
API->>DB: For each institution_id, create 'calendar_entries_institutions' record
API->>DB: Log in 'audit_logs'
alt DB Operation Fails
API->>DB: Rollback
API->>UI: Respond 500
else Success
DB->>API: Commit, Records created
API->>UI: Success response (201 Created)
UI->>Manager: Display 'Success', Entry on calendar
end
Superadmins and Admins review audit_logs to track system actions.
(This flow remains largely the same as it's about a generic logging table, but the entities being logged are now more diverse).
(Same as previous)
flowchart TD
A["Start: Admin/Superadmin navigates to Audit Logs section"] --> B["UI: Displays recent audit logs (paginated)"];
B --> C["User applies filters (entity_name, entity_id, action, user_id, date_range)"];
C --> D["Clicks 'Apply Filters'"];
D --> E["API: GET /api/audit-logs with filter params"];
E --> F{"Backend: Auth, Validate Filters, Query 'audit_logs', Paginate"};
F -- Success --> G["UI: Displays filtered, paginated audit logs"];
F -- "Error (auth, invalid filter, server error)" --> H["API 4xx/500, UI: Error message"];
G --> C;
H --> C;
G --> Z["End / View Log Details (old_value, new_value)"];
- Real-Time Updates: Leverage real-time updates (e.g., WebSockets) for dynamic information like event status, resource availability, and patient tracking.
- Error Handling: Robust API error handling with clear HTTP status codes and messages.
-
Data Privacy & Visibility: Enforce
Visibilityenums and role-based access control (RBAC) diligently at the backend. - Idempotency: Ensure critical operations are idempotent where appropriate.
- API Versioning: Consider for long-term maintainability.
- Transaction Management: Wrap related database operations in transactions to ensure atomicity.
We are always looking for feedback and contributions to improve StateForce. Feel free to open issues, suggest edits, or submit pull requests to the repository.
- Repo: StateForce GitHub
- Contact: martinmendozadev@gmail.com
If you encounter issues or need assistance, please reach out via:
- Email: martinmendozadev@gmail.com
- GitHub Issues: Submit an Issue
This documentation and the StateForce platform are licensed under the Apache License 2.0.
Thank you for using StateForce! π¨
Together, we are improving emergency response operations in real-time.
Welcome to the StateForce Wiki! Use this sidebar to navigate through the documentation.
This sidebar provides quick access to all the documentation pages. For detailed information, click on the desired section.