# Stateflow 状态流转系统

## 架构概述

Stateflow 是一个基于日志的订单状态流转管理系统，采用服务层模式实现业务逻辑与数据访问的分离。

### 核心概念

- **State (状态)**: 流程中的一个节点，可以附带参数
- **Process (流程模板)**: 由多个有序状态组成的流程定义
- **Order (订单实例)**: 流程的具体执行实例
- **OrderStateLog (完成日志)**: 记录订单完成每个状态的时间点和操作人

## 数据模型

### State
```python
State(name, parameters=[StateParameter(...)])
```
- 状态节点定义
- 支持附加参数（键值对）

### Process
```python
Process(name, state_nodes=ManyToMany[ProcessNode])
```
- 流程模板，定义状态流转顺序
- 通过 `ProcessNode` 中间表关联 `State`，支持排序

### ProcessNode
```python
ProcessNode(process, state, order)
```
- Process 和 State 的多对多关联表
- `order` 字段定义状态在流程中的执行顺序

### Order
```python
Order(process, metadata={})
```
- 流程的具体实例
- **不存储** `current_state` 字段
- 当前状态通过查询 `OrderStateLog` 推导

### OrderStateLog
```python
OrderStateLog(order, state, completed_at, completed_by, is_cancelled, cancelled_at)
```
- 记录订单完成某个状态的日志
- `completed_at`: 完成时间
- `completed_by`: 操作人
- `is_cancelled`: 是否已撤销
- `cancelled_at`: 撤销时间
- 唯一约束: `(order, state)` - 每个状态只能有一条记录
- **不允许删除**，重置进度时只标记为已撤销

## 核心逻辑

### 状态推导规则

当前状态的推导遵循以下规则：

1. **未开始**: 没有任何有效完成日志（或所有记录都被撤销） → 返回 `None`
2. **进行中**: 有部分完成日志 → 返回下一个未完成的状态
3. **已完成**: 所有状态都已完成 → 返回 `None`

**重要**: 初始状态是 `None`（未开始），而不是第一个节点。

示例：
```python
from stateflow.services import get_order_current_state, get_overall_status

# 获取当前状态（None = 未开始或已完成）
current_state = get_order_current_state(order)

# 获取整体状态类型
status = get_overall_status(order)  # 'not_started', 'in_progress', 'completed'
```

### 状态推进

```python
from stateflow.services import advance_to_next_state

# 推进到下一个状态（需要传入操作人）
success = advance_to_next_state(order, completed_by=request.user)
```

推进规则：
- 如果是初始状态（`None`），推进到第一个节点
- 自动查找当前状态
- 验证是否可以推进（是否已完成）
- 创建 `OrderStateLog` 记录完成时间和操作人
- 返回 `(True, message)` 表示成功，`(False, reason)` 表示失败

### 完整时间线

```python
from stateflow.services import get_order_state_timeline

# 获取完整的状态时间线
timeline = get_order_state_timeline(order)
# [
#   {'state': State1, 'completed_at': datetime, 'completed_by': User, 'is_completed': True},
#   {'state': State2, 'completed_at': None, 'completed_by': None, 'is_completed': False},
#   ...
# ]
```

## 服务层 API

所有业务逻辑封装在 `stateflow/services.py` 中，可在 Admin、API、任务队列等场景复用。

### 主要函数

#### `get_order_current_state(order) -> State | None`
获取订单当前应处理的状态。

#### `get_overall_status(order) -> str`
返回订单整体状态：
- `'not_started'`: 未开始
- `'in_progress'`: 进行中
- `'completed'`: 已完成

#### `get_order_state_status(order, state) -> str`
返回订单中某个状态的状态：
- `'not_started'`: 未开始
- `'in_progress'`: 进行中
- `'completed'`: 已完成

#### `advance_to_next_state(order, completed_by) -> Tuple[bool, str]`
推进到下一个状态，创建完成日志。返回 (是否成功, 消息)。

#### `get_order_state_timeline(order) -> List[dict]`
获取完整时间线，包含所有状态的完成情况（包括已撤销的记录）。

#### `get_progress_percentage(order) -> float`
计算完成进度百分比（0.0 - 100.0）。

#### `reset_order_progress(order)`
重置订单进度。注意：**不删除日志记录**，而是标记为已撤销并记录撤销时间，保留完整的操作历史。

#### `can_advance_to_next_state(order) -> Tuple[bool, str]`
检查是否可以继续推进。返回 (是否可以推进, 原因)。

## 使用示例

### 1. 创建流程模板

```python
from stateflow.models import State, Process, ProcessNode

# 创建状态
pending = State.objects.create(name="待审核")
approved = State.objects.create(name="已审核")
shipped = State.objects.create(name="已发货")

# 创建流程
process = Process.objects.create(name="订单流程")

# 关联状态（设置顺序）
ProcessNode.objects.create(process=process, state=pending, order=1)
ProcessNode.objects.create(process=process, state=approved, order=2)
ProcessNode.objects.create(process=process, state=shipped, order=3)
```

### 2. 创建订单并推进

```python
from stateflow.models import Order
from stateflow.services import get_order_current_state, advance_to_next_state, get_overall_status

# 创建订单实例
order = Order.objects.create(process=process, metadata={'order_no': 'SO-001'})

# 查看当前状态（初始状态是 None）
current = get_order_current_state(order)  # None
status = get_overall_status(order)  # 'not_started'

# 推进到第一个状态
success, msg = advance_to_next_state(order, completed_by=request.user)

current = get_order_current_state(order)  # approved

# 推进到下一个状态
success, msg = advance_to_next_state(order, completed_by=request.user)

current = get_order_current_state(order)  # shipped
```

### 3. 在 API 中使用

```python
from rest_framework.decorators import action
from rest_framework.response import Response
from stateflow.services import advance_to_next_state, get_order_state_timeline

class OrderViewSet(viewsets.ModelViewSet):
    
    @action(detail=True, methods=['post'])
    def advance(self, request, pk=None):
        order = self.get_object()
        success, message = advance_to_next_state(order, completed_by=request.user)
        
        if success:
            return Response({'status': 'advanced', 'message': message})
        return Response({'status': 'failed', 'message': message}, status=400)
    
    @action(detail=True, methods=['get'])
    def timeline(self, request, pk=None):
        order = self.get_object()
        timeline = get_order_state_timeline(order)
        return Response(timeline)
```

## Admin 配置

Admin 界面提供以下功能：

1. **State 管理**: 创建和编辑状态，支持内联编辑参数
2. **Process 管理**: 定义流程，通过内联表添加有序状态节点
3. **Order 管理**: 
   - 查看完成日志（只读内联）
   - 批量操作：推进到下一状态、重置进度
   - 显示当前状态、完成百分比
4. **OrderStateLog 管理**: 只读日志查看，用于审计

## 迁移历史

- `0001_initial.py`: 初始模型（State, Process with CharField state_nodes）
- `0002-0007`: 其他应用迁移
- `0008_process_state_nodes_remove_process_current_state...`: 将 state_nodes 改为 ManyToMany，创建 ProcessNode 和 Order
- `0009_remove_order_current_state_orderstatelog`: 移除 Order.current_state，创建 OrderStateLog

## 测试

运行测试：
```bash
python manage.py test stateflow
```

测试覆盖：
- ✅ 初始状态推导
- ✅ 状态推进逻辑
- ✅ 状态类型判断
- ✅ 完整时间线生成
- ✅ 进度重置

## 设计优势

1. **审计完整**: 每次状态变更都有时间和操作人记录
2. **数据一致**: 状态从日志推导，无冗余存储
3. **逻辑复用**: 服务层可在 Admin/API/Task 中共享
4. **灵活扩展**: 可轻松添加状态前置条件、权限检查等
5. **可追溯**: 通过 OrderStateLog 实现完整的操作历史
6. **历史保留**: 重置进度时不删除记录，保留完整的操作痕迹
7. **撤销追踪**: 记录撤销时间，方便审计和问题追溯

## ProcessNode vs OrderStateLog

很多人会混淆这两个表，这里做详细说明：

### ProcessNode (流程模板)
- **作用**: 定义流程包含哪些状态，以及执行顺序
- **关系**: Process ↔ State 的多对多关联
- **层级**: 模板层（一对多）
- **类比**: "菜谱"，定义做菜的步骤
- **示例**: 订单流程 = [待审核(1) → 已审核(2) → 已发货(3)]

### OrderStateLog (订单实例)
- **作用**: 记录某个订单完成了哪些状态，以及完成时间、操作人
- **关系**: Order → State 的完成记录
- **层级**: 实例层（每个订单独立）
- **类比**: "做菜记录"，记录实际做了什么、何时做的
- **示例**: 订单#001 在 2025-01-10 由张三完成了"待审核"状态

## 注意事项

1. **唯一约束**: 每个 `(order, state)` 只能有一条记录
2. **顺序性**: 必须按 ProcessNode.order 顺序完成，不能跳过
3. **操作人必填**: `advance_to_next_state()` 必须传入 `completed_by` 参数
4. **不可删除**: OrderStateLog 不允许删除，只能标记为已撤销
5. **保留历史**: 重置进度时保留所有历史记录，并记录撤销时间
6. **初始状态**: 新订单的初始状态是 `None`（未开始），而不是第一个节点
