- Introduced reusable test utilities in `backend/tests/utils` for FSM transitions, HTMX interactions, and common scenarios. - Added factory functions for creating test submissions, parks, rides, and photo submissions. - Implemented assertion helpers for verifying state changes, toast notifications, and transition logs. - Created comprehensive state machine diagrams for all FSM-enabled models in `docs/STATE_DIAGRAMS.md`, detailing states, transitions, and guard conditions.
12 KiB
State Machine Diagrams
This document provides comprehensive state diagrams for all FSM-enabled models in ThrillWiki. These diagrams show all possible states, transitions, and guard conditions.
Table of Contents
- EditSubmission State Machine
- PhotoSubmission State Machine
- Park Status State Machine
- Ride Status State Machine
- ModerationReport State Machine
- ModerationQueue State Machine
- BulkOperation State Machine
EditSubmission State Machine
EditSubmission tracks user-submitted edits through the moderation workflow.
stateDiagram-v2
[*] --> PENDING: User submits edit
PENDING --> APPROVED: transition_to_approved()
PENDING --> REJECTED: transition_to_rejected()
PENDING --> ESCALATED: transition_to_escalated()
ESCALATED --> APPROVED: transition_to_approved()
ESCALATED --> REJECTED: transition_to_rejected()
APPROVED --> [*]
REJECTED --> [*]
note right of PENDING
Initial state
Yellow badge
end note
note right of APPROVED
Final state
Green badge
Changes applied
end note
note right of REJECTED
Final state
Red badge
end note
note right of ESCALATED
Orange badge
Needs admin review
end note
States
| State | Color | Description |
|---|---|---|
| PENDING | Yellow | Initial state, awaiting moderator review |
| APPROVED | Green | Final state, changes have been applied |
| REJECTED | Red | Final state, changes were declined |
| ESCALATED | Orange | Needs higher-level review |
Transitions
| Transition | From | To | Guard | Description |
|---|---|---|---|---|
transition_to_approved |
PENDING, ESCALATED | APPROVED | is_moderator |
Approve and apply changes |
transition_to_rejected |
PENDING, ESCALATED | REJECTED | is_moderator |
Reject with reason |
transition_to_escalated |
PENDING | ESCALATED | is_moderator |
Escalate to admin |
PhotoSubmission State Machine
PhotoSubmission tracks user-submitted photos through moderation.
stateDiagram-v2
[*] --> PENDING: User uploads photo
PENDING --> APPROVED: transition_to_approved()
PENDING --> REJECTED: transition_to_rejected()
PENDING --> ESCALATED: transition_to_escalated()
ESCALATED --> APPROVED: transition_to_approved()
ESCALATED --> REJECTED: transition_to_rejected()
APPROVED --> [*]
REJECTED --> [*]
note right of APPROVED
Photo added to gallery
end note
States
| State | Color | Description |
|---|---|---|
| PENDING | Yellow | Awaiting moderator review |
| APPROVED | Green | Photo approved and visible |
| REJECTED | Red | Photo rejected |
| ESCALATED | Orange | Needs admin review |
Park Status State Machine
Park status tracks the operational status of theme parks.
stateDiagram-v2
[*] --> OPERATING: Park opens
[*] --> UNDER_CONSTRUCTION: Park announced
UNDER_CONSTRUCTION --> OPERATING: transition_to_operating()
OPERATING --> CLOSED_TEMP: transition_to_closed_temp()
OPERATING --> CLOSED_PERM: transition_to_closed_perm()
OPERATING --> UNDER_CONSTRUCTION: transition_to_under_construction()
CLOSED_TEMP --> OPERATING: transition_to_operating()
CLOSED_TEMP --> CLOSED_PERM: transition_to_closed_perm()
CLOSED_PERM --> DEMOLISHED: transition_to_demolished()
CLOSED_PERM --> RELOCATED: transition_to_relocated()
CLOSED_PERM --> OPERATING: transition_to_operating()
DEMOLISHED --> [*]
RELOCATED --> [*]
note right of OPERATING
Green badge
Normal operations
end note
note right of CLOSED_TEMP
Yellow badge
Seasonal or temporary
end note
note right of CLOSED_PERM
Red badge
Permanently closed
end note
note left of DEMOLISHED
Gray badge
Final state
end note
note left of RELOCATED
Gray badge
Final state
end note
States
| State | Color | Description |
|---|---|---|
| OPERATING | Green | Park is open and operating |
| UNDER_CONSTRUCTION | Blue | Park is being built |
| CLOSED_TEMP | Yellow | Temporarily closed (seasonal, renovation) |
| CLOSED_PERM | Red | Permanently closed |
| DEMOLISHED | Gray | Park has been demolished |
| RELOCATED | Gray | Park has moved to new location |
Transitions
| Transition | From | To | Guard | Description |
|---|---|---|---|---|
transition_to_operating |
CLOSED_TEMP, CLOSED_PERM, UNDER_CONSTRUCTION | OPERATING | is_moderator |
Reopen park |
transition_to_closed_temp |
OPERATING | CLOSED_TEMP | is_moderator |
Close temporarily |
transition_to_closed_perm |
OPERATING, CLOSED_TEMP | CLOSED_PERM | is_moderator |
Close permanently |
transition_to_demolished |
CLOSED_PERM | DEMOLISHED | is_moderator |
Mark as demolished |
transition_to_relocated |
CLOSED_PERM | RELOCATED | is_moderator |
Mark as relocated |
transition_to_under_construction |
OPERATING | UNDER_CONSTRUCTION | is_moderator |
Mark under construction |
Ride Status State Machine
Ride status tracks the operational status of individual rides within parks.
stateDiagram-v2
[*] --> OPERATING: Ride opens
[*] --> UNDER_CONSTRUCTION: Ride announced
UNDER_CONSTRUCTION --> OPERATING: transition_to_operating()
OPERATING --> CLOSED_TEMP: transition_to_closed_temp()
OPERATING --> SBNO: transition_to_sbno()
OPERATING --> CLOSING: transition_to_closing()
OPERATING --> CLOSED_PERM: transition_to_closed_perm()
CLOSED_TEMP --> OPERATING: transition_to_operating()
CLOSED_TEMP --> CLOSED_PERM: transition_to_closed_perm()
SBNO --> OPERATING: transition_to_operating()
SBNO --> CLOSED_PERM: transition_to_closed_perm()
SBNO --> DEMOLISHED: transition_to_demolished()
CLOSING --> CLOSED_PERM: apply_post_closing_status()
CLOSING --> OPERATING: transition_to_operating()
CLOSED_PERM --> DEMOLISHED: transition_to_demolished()
CLOSED_PERM --> RELOCATED: transition_to_relocated()
CLOSED_PERM --> OPERATING: transition_to_operating()
DEMOLISHED --> [*]
RELOCATED --> [*]
note right of SBNO
Amber badge
Standing But Not Operating
end note
note right of CLOSING
Orange badge
Closing date announced
Auto-transitions when date passes
end note
States
| State | Color | Description |
|---|---|---|
| OPERATING | Green | Ride is open and operating |
| UNDER_CONSTRUCTION | Blue | Ride is being built |
| CLOSED_TEMP | Yellow | Temporarily closed (maintenance, seasonal) |
| SBNO | Amber | Standing But Not Operating |
| CLOSING | Orange | Closing date announced, countdown to close |
| CLOSED_PERM | Red | Permanently closed |
| DEMOLISHED | Gray | Ride has been removed |
| RELOCATED | Gray | Ride has moved to new park |
Special: CLOSING Status
The CLOSING status has special behavior:
- When a ride enters CLOSING, a
closing_dateshould be set - When the closing date passes,
apply_post_closing_status()is called - The ride transitions to the
post_closing_status(default: CLOSED_PERM) - This allows announcing closures ahead of time
ModerationReport State Machine
ModerationReport tracks user reports about content or behavior.
stateDiagram-v2
[*] --> PENDING: User submits report
PENDING --> INVESTIGATING: transition_to_investigating()
PENDING --> DISMISSED: transition_to_dismissed()
INVESTIGATING --> RESOLVED: transition_to_resolved()
INVESTIGATING --> DISMISSED: transition_to_dismissed()
INVESTIGATING --> ESCALATED: transition_to_escalated()
ESCALATED --> RESOLVED: transition_to_resolved()
ESCALATED --> DISMISSED: transition_to_dismissed()
RESOLVED --> [*]
DISMISSED --> [*]
note right of INVESTIGATING
Blue badge
Moderator reviewing
end note
note right of RESOLVED
Green badge
Action taken
end note
note right of DISMISSED
Gray badge
No action needed
end note
States
| State | Color | Description |
|---|---|---|
| PENDING | Yellow | Report awaiting review |
| INVESTIGATING | Blue | Moderator is reviewing |
| ESCALATED | Orange | Needs admin attention |
| RESOLVED | Green | Action taken, issue addressed |
| DISMISSED | Gray | Report dismissed, no action needed |
ModerationQueue State Machine
ModerationQueue tracks workflow items for moderators.
stateDiagram-v2
[*] --> PENDING: Item created
PENDING --> IN_PROGRESS: transition_to_in_progress()
PENDING --> CANCELLED: transition_to_cancelled()
IN_PROGRESS --> COMPLETED: transition_to_completed()
IN_PROGRESS --> CANCELLED: transition_to_cancelled()
IN_PROGRESS --> PENDING: transition_to_pending()
COMPLETED --> [*]
CANCELLED --> [*]
note right of IN_PROGRESS
Blue badge
Being worked on
end note
note right of COMPLETED
Green badge
Task finished
end note
States
| State | Color | Description |
|---|---|---|
| PENDING | Yellow | Waiting to be picked up |
| IN_PROGRESS | Blue | Currently being worked on |
| COMPLETED | Green | Task finished successfully |
| CANCELLED | Gray | Task cancelled |
BulkOperation State Machine
BulkOperation tracks large-scale administrative operations.
stateDiagram-v2
[*] --> PENDING: Operation created
PENDING --> RUNNING: transition_to_running()
PENDING --> CANCELLED: transition_to_cancelled()
RUNNING --> COMPLETED: transition_to_completed()
RUNNING --> FAILED: transition_to_failed()
RUNNING --> CANCELLED: transition_to_cancelled()
COMPLETED --> [*]
FAILED --> [*]
CANCELLED --> [*]
note right of RUNNING
Blue badge
Processing items
Shows progress %
end note
note right of FAILED
Red badge
Error occurred
end note
States
| State | Color | Description |
|---|---|---|
| PENDING | Yellow | Scheduled, waiting to start |
| RUNNING | Blue | Currently processing |
| COMPLETED | Green | Finished successfully |
| FAILED | Red | Encountered error |
| CANCELLED | Gray | Manually cancelled |
Common Patterns
Permission Guards
All transitions include permission guards:
@transition(
field=status,
source='PENDING',
target='APPROVED',
permission='apps.moderation.can_approve_submission'
)
def transition_to_approved(self, user=None):
pass
Confirmation Requirements
Dangerous transitions require confirmation in the UI:
- Reject (any submission)
- Cancel (any operation)
- Close Permanently (park/ride)
- Demolish (park/ride)
Toast Notifications
All transitions trigger toast notifications:
| Transition Type | Toast Color | Icon |
|---|---|---|
| Approve | Green | check |
| Reject | Red | times |
| Escalate | Orange | arrow-up |
| Complete | Green | check-circle |
| Cancel | Red | ban |
Testing Transitions
See the test documentation:
- Unit tests:
backend/apps/*/tests.py - Integration tests:
backend/tests/integration/test_fsm_transition_view.py - E2E tests:
backend/tests/e2e/test_*_fsm.py - Manual testing:
backend/tests/e2e/BROWSER_TESTING_CHECKLIST.md
Implementation Notes
Adding New Transitions
- Add the transition method to the model with
@transitiondecorator - Define source states, target state, and permission guard
- Update the template to show the new button
- Add tests for the new transition
- Update this documentation
State Field Configuration
States are defined using RichFSMField which integrates with:
- django-fsm for transition logic
- django-fsm-log for transition history
- RichChoices for metadata (colors, icons, labels)
status = RichFSMField(
choice_group="statuses",
domain="moderation",
max_length=20,
default="PENDING"
)