1
0
forked from erp-dev/erp

fix: process id change when plate_order and printing_order update

This commit is contained in:
2026-01-15 16:35:46 +08:00
parent 9a367caab7
commit ea9f378de9
9 changed files with 384 additions and 8 deletions

View File

@@ -14,6 +14,65 @@ from . import models
logger = logging.getLogger(__name__)
User = get_user_model()
def _can_relink_business_object(business_object: 'models.BusinessObject') -> bool:
"""
内部判断:该 BusinessObject 是否允许“换流程并重建”relink
规则(与 printing.models.PlateOrder/PrintingJob.has_started 保持一致):
- 只要存在未撤销is_cancelled=False的状态记录就视为已开始不允许 relink
"""
if not business_object:
return True
return not business_object.state_logs.filter(is_cancelled=False).exists()
def relink_business_object_for_instance(
*,
instance,
new_process: 'models.Process',
default_name: str | None = None,
default_description: str | None = None,
) -> Optional['models.BusinessObject']:
"""
当业务对象的“流程”发生变更时,重建并重新绑定一个新的 BusinessObject。
设计目标:
- stateflow 层提供统一逻辑(不依赖 printing/shipment 等业务模块)
- 仅在“没有未撤销进度”的情况下允许重建
- 旧 BusinessObject 不删除(未来可通过“无反向引用”视为悬空)
返回:
- BusinessObject 实例relink 成功后的新 BO
- None不允许 relink例如已存在未撤销进度调用方应将其转为 400
注意:
- 若 instance 原本没有 business_object本函数仍会创建并绑定新的 BO
- 本函数只负责 BO 的创建与绑定,不负责写入业务对象自身的 process 字段
"""
if instance is None or getattr(instance, 'pk', None) is None:
return None
if new_process is None:
return None
old_bo = getattr(instance, 'business_object', None)
if old_bo and not _can_relink_business_object(old_bo):
return None
ct = ContentType.objects.get_for_model(instance.__class__)
bo = models.BusinessObject.objects.create(
name=(default_name or f"{instance.__class__.__name__}-{instance.pk}"),
process=new_process,
description=(default_description or ''),
content_type=ct,
object_id=instance.pk,
)
# 绑定到业务对象(业务对象侧通常为 OneToOneField
setattr(instance, 'business_object', bo)
instance.save(update_fields=['business_object'])
return bo
def ensure_business_object_bound_to_instance(
business_object: 'models.BusinessObject',
instance,