1
0
forked from erp-dev/erp
Files
erpnew/api_v2/views/stateflow.py

102 lines
4.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
class BusinessObjectCloneRequestSerializer(serializers.Serializer):
business_object_id = serializers.IntegerField(min_value=1)
# 调用方必须显式传入 content_type 与 object_id
# - content_type仅用于校验与源对象一致不做额外校验
# - object_id克隆后的新业务对象 ID必须与源对象不同
content_type = serializers.IntegerField(min_value=1, allow_null=True)
object_id = serializers.IntegerField(min_value=1, allow_null=True)
class BusinessObjectCloneView(APIView):
"""
克隆 BusinessObject含所有状态流转记录与工艺参数记录
POST /api/v2/stateflow/business-objects/clone/
请求体:
{
"business_object_id": 123,
"content_type": 9,
"object_id": 456
}
返回:
{
"business_object_id": 456
}
"""
permission_classes = [permissions.IsAuthenticated]
def post(self, request):
srz = BusinessObjectCloneRequestSerializer(data=request.data)
srz.is_valid(raise_exception=True)
bo_id = srz.validated_data['business_object_id']
expected_content_type_id = srz.validated_data.get('content_type')
new_object_id = srz.validated_data.get('object_id')
try:
bo = stateflow_models.BusinessObject.objects.get(id=bo_id)
except stateflow_models.BusinessObject.DoesNotExist:
return Response({'detail': 'business_object 不存在'}, status=status.HTTP_404_NOT_FOUND)
try:
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)
return Response({'business_object_id': cloned.id})