1
0
forked from erp-dev/erp

fix: business.object_id maybe null, missing parameters when plate-Order cloned

This commit is contained in:
2025-12-17 11:02:07 +08:00
parent 639efe8421
commit 51fad953c3
24 changed files with 13247 additions and 47 deletions

View File

@@ -1,6 +1,8 @@
from rest_framework import serializers, status, permissions
from rest_framework.response import Response
from rest_framework.views import APIView
from django.core.exceptions import FieldDoesNotExist
from django.db import transaction
from stateflow import models as stateflow_models
from stateflow import services as stateflow_services
@@ -49,11 +51,48 @@ class BusinessObjectCloneView(APIView):
return Response({'detail': 'business_object 不存在'}, status=status.HTTP_404_NOT_FOUND)
try:
cloned = stateflow_services.clone_business_object(
bo,
new_object_id=new_object_id,
expected_content_type_id=expected_content_type_id,
)
with transaction.atomic():
cloned = stateflow_services.clone_business_object(
bo,
new_object_id=new_object_id,
expected_content_type_id=expected_content_type_id,
)
# 兼容 printing 的“克隆=新建后复制流程进度”工作流:
# 目标业务对象PlateOrder/PrintingJob本身持有 business_object 字段,
# 需要把克隆后的 BusinessObject 回写到目标对象上,否则前端看不到节点/参数历史。
try:
target_obj = cloned.content_type.get_object_for_this_type(pk=cloned.object_id)
except Exception:
target_obj = None
if target_obj is not None:
try:
bo_field = target_obj._meta.get_field('business_object')
except FieldDoesNotExist:
bo_field = None
if bo_field is not None and bo_field.related_model is stateflow_models.BusinessObject:
old_bo_id = getattr(target_obj, 'business_object_id', None)
target_obj.business_object = cloned
target_obj.save(update_fields=['business_object'])
# 如果目标对象在创建时自动生成了一个“空 business_object”这里做安全清理
# 避免同一个业务对象存在多个 BusinessObject 绑定导致后续审计/排查混乱。
if old_bo_id and old_bo_id != cloned.id:
old_bo = (
stateflow_models.BusinessObject.objects
.filter(id=old_bo_id)
.select_related('content_type')
.first()
)
if (
old_bo
and old_bo.state_logs.count() == 0
and old_bo.content_type_id == cloned.content_type_id
and old_bo.object_id == cloned.object_id
):
old_bo.delete()
except ValueError as e:
return Response({'detail': str(e)}, status=status.HTTP_400_BAD_REQUEST)