1
0
forked from erp-dev/erp

patch: patch testing (api & services)

This commit is contained in:
2025-11-17 10:10:32 +08:00
parent 9c38e2ac09
commit 02a1b77e19
10 changed files with 337 additions and 102 deletions

View File

@@ -11,27 +11,24 @@ User = get_user_model()
def get_business_object_current_state(business_object: 'models.BusinessObject') -> Optional['models.State']:
"""
获取业务对象的当前状态(最后完成的状态
获取业务对象的当前状态(下一个待执行的节点
规则:
1. 如果没有任何完成记录(或所有记录都被撤销),返回 None未开始
2. 如果有完成记录,返回最后完成的状态(进行中或已完成)
- 返回下一个待执行的节点(第一个未完成的节点
- 如果所有节点都已完成,返回 None
注意current_state 表示"最后完成的状态",而不是"待执行的状态"
注意current_state 始终返回"下一个待执行的节点",配合进度可以判断具体状态
- 进度 0% + current_state 非空 → 显示"未开始"(还没开始执行,但知道第一个节点是什么)
- 进度 > 0% + current_state 非空 → 显示 current_state.name正在进行
- current_state = None → 显示"已完成"(没有待执行的节点了)
"""
# 获取最后一条完成且未撤销的记录
last_completed_record = (
business_object.state_logs
.filter(is_cancelled=False)
.select_related('state')
.order_by('-completed_at', '-id')
.first()
)
# 使用 get_next_pending_state 获取下一个待执行的节点
next_pending = get_next_pending_state(business_object, include_parameters=False)
if last_completed_record:
return last_completed_record.state
if next_pending:
return next_pending['state']
# 没有任何完成记录,返回 None(未开始)
# 所有节点都已完成,返回 None
return None
@@ -239,13 +236,13 @@ def can_advance_to_next_state(business_object: 'models.BusinessObject') -> Tuple
def get_business_object_state_timeline(business_object: 'models.BusinessObject') -> List[dict]:
"""
获取业务对象状态时间线(包括未开始和已完成的状态)
获取业务对象状态时间线(包括未开始、进行中和已完成的状态)
返回格式:
[
{
'state': State对象,
'status': 'not_started' | 'completed' | 'cancelled',
'status': 'not_started' | 'in_progress' | 'completed' | 'cancelled',
'order': 顺序号,
'completed_at': 完成时间(如果已完成),
'completed_by': 完成人(如果已完成),
@@ -254,6 +251,12 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject')
},
...
]
状态判断规则:
- cancelled: 有日志记录且已撤销
- completed: 有日志记录且未撤销
- in_progress: 没有日志记录,但是 current_state下一个待执行的节点且已有完成记录
- not_started: 其他未开始的节点
"""
timeline = []
process_nodes = business_object.process.process_nodes.select_related('state').order_by('order', 'id')
@@ -264,6 +267,13 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject')
for log in business_object.state_logs.select_related('completed_by')
}
# 获取 current_state下一个待执行的节点
current_state = get_business_object_current_state(business_object)
current_state_id = current_state.id if current_state else None
# 检查是否有任何完成记录
has_any_completed = business_object.state_logs.filter(is_cancelled=False).exists()
for node in process_nodes:
state = node.state
log = state_logs_map.get(state.id)
@@ -278,7 +288,12 @@ def get_business_object_state_timeline(business_object: 'models.BusinessObject')
cancelled_at = log.cancelled_at
is_cancelled = log.is_cancelled
else:
status = 'not_started'
# 未开始的节点,判断是 in_progress 还是 not_started
# 如果是 current_state 且有任何完成记录,则为 in_progress
if has_any_completed and state.id == current_state_id:
status = 'in_progress'
else:
status = 'not_started'
completed_at = None
completed_by = None
cancelled_at = None