mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-22 16:51:09 -05:00
- 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.
462 lines
12 KiB
Markdown
462 lines
12 KiB
Markdown
# 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
|
|
|
|
1. [EditSubmission State Machine](#editsubmission-state-machine)
|
|
2. [PhotoSubmission State Machine](#photosubmission-state-machine)
|
|
3. [Park Status State Machine](#park-status-state-machine)
|
|
4. [Ride Status State Machine](#ride-status-state-machine)
|
|
5. [ModerationReport State Machine](#moderationreport-state-machine)
|
|
6. [ModerationQueue State Machine](#moderationqueue-state-machine)
|
|
7. [BulkOperation State Machine](#bulkoperation-state-machine)
|
|
|
|
---
|
|
|
|
## EditSubmission State Machine
|
|
|
|
EditSubmission tracks user-submitted edits through the moderation workflow.
|
|
|
|
```mermaid
|
|
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.
|
|
|
|
```mermaid
|
|
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.
|
|
|
|
```mermaid
|
|
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.
|
|
|
|
```mermaid
|
|
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_date` should 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.
|
|
|
|
```mermaid
|
|
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.
|
|
|
|
```mermaid
|
|
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.
|
|
|
|
```mermaid
|
|
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:
|
|
|
|
```python
|
|
@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
|
|
|
|
1. Add the transition method to the model with `@transition` decorator
|
|
2. Define source states, target state, and permission guard
|
|
3. Update the template to show the new button
|
|
4. Add tests for the new transition
|
|
5. 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)
|
|
|
|
```python
|
|
status = RichFSMField(
|
|
choice_group="statuses",
|
|
domain="moderation",
|
|
max_length=20,
|
|
default="PENDING"
|
|
)
|
|
```
|