|
|
@@ -27,6 +27,7 @@ import json
|
|
|
from collections import defaultdict
|
|
|
logger = logging.getLogger(__name__)
|
|
|
from operation_log.views import log_operation,log_failure_operation,log_success_operation
|
|
|
+from operation_log.models import OperationLog
|
|
|
# 库位分配
|
|
|
# 入库规则函数
|
|
|
# 逻辑根据批次下的托盘数目来找满足区间范围的库位,按照优先级排序,
|
|
|
@@ -96,11 +97,66 @@ class locationViewSet(viewsets.ModelViewSet):
|
|
|
def get_serializer_class(self):
|
|
|
if self.action == 'list':
|
|
|
return LocationListSerializer
|
|
|
+ elif self.action == 'create':
|
|
|
+ return LocationPostSerializer
|
|
|
elif self.action == 'update':
|
|
|
return LocationPostSerializer
|
|
|
elif self.action =='retrieve':
|
|
|
return LocationListSerializer
|
|
|
|
|
|
+ def create(self, request, *args, **kwargs):
|
|
|
+ """创建库位"""
|
|
|
+ serializer = self.get_serializer(data=request.data)
|
|
|
+ try:
|
|
|
+ serializer.is_valid(raise_exception=True)
|
|
|
+ instance = serializer.save()
|
|
|
+ log_success_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"创建库位成功,库位编码: {instance.location_code}",
|
|
|
+ operation_level="new",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=instance.id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ headers = self.get_success_headers(serializer.data)
|
|
|
+ return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
|
|
+ except Exception as e:
|
|
|
+ log_failure_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"创建库位失败: {str(e)}",
|
|
|
+ operation_level="new",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ raise
|
|
|
+
|
|
|
+ def destroy(self, request, *args, **kwargs):
|
|
|
+ """删除库位"""
|
|
|
+ instance = self.get_object()
|
|
|
+ location_code = instance.location_code
|
|
|
+ object_id = instance.id
|
|
|
+ try:
|
|
|
+ self.perform_destroy(instance)
|
|
|
+ log_success_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"删除库位成功,库位编码: {location_code}",
|
|
|
+ operation_level="delete",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=object_id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
+ except Exception as e:
|
|
|
+ log_failure_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"删除库位失败,库位编码: {location_code}, 错误: {str(e)}",
|
|
|
+ operation_level="delete",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=object_id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ raise
|
|
|
+
|
|
|
def update(self, request, *args, **kwargs):
|
|
|
qs = self.get_object()
|
|
|
data = self.request.data
|
|
|
@@ -307,12 +363,29 @@ class locationGroupViewSet(viewsets.ModelViewSet):
|
|
|
id = self.get_project()
|
|
|
if self.request.auth:
|
|
|
if id is None:
|
|
|
+ log_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content="查看库位组列表",
|
|
|
+ operation_level="view",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
return LocationGroupModel.objects.filter()
|
|
|
else:
|
|
|
+ log_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"查看库位组详情 ID:{id}",
|
|
|
+ operation_level="view",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
return LocationGroupModel.objects.filter(id=id)
|
|
|
else:
|
|
|
return LocationGroupModel.objects.none()
|
|
|
- def get_serializer_class(self):
|
|
|
+ def get_serializer_class(self):
|
|
|
+ if self.action == 'create':
|
|
|
+ return LocationGroupPostSerializer
|
|
|
if self.action == 'list':
|
|
|
return LocationGroupListSerializer
|
|
|
|
|
|
@@ -320,7 +393,63 @@ class locationGroupViewSet(viewsets.ModelViewSet):
|
|
|
return LocationGroupPostSerializer
|
|
|
|
|
|
elif self.action =='retrieve':
|
|
|
- return LocationGroupListSerializer
|
|
|
+ return LocationGroupListSerializer
|
|
|
+
|
|
|
+ def create(self, request, *args, **kwargs):
|
|
|
+ """创建库位组"""
|
|
|
+ data = self.request.data.copy()
|
|
|
+ order_month = str(timezone.now().strftime('%Y%m'))
|
|
|
+ data['month'] = order_month
|
|
|
+ serializer = LocationGroupPostSerializer(data=data)
|
|
|
+ try:
|
|
|
+ serializer.is_valid(raise_exception=True)
|
|
|
+ instance = serializer.save()
|
|
|
+ log_success_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"创建库位组成功,库位组编码: {instance.group_code}",
|
|
|
+ operation_level="new",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=instance.id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ headers = self.get_success_headers(serializer.data)
|
|
|
+ return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
|
|
+ except Exception as e:
|
|
|
+ log_failure_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"创建库位组失败: {str(e)}",
|
|
|
+ operation_level="new",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ raise
|
|
|
+
|
|
|
+ def destroy(self, request, *args, **kwargs):
|
|
|
+ """删除库位组"""
|
|
|
+ instance = self.get_object()
|
|
|
+ group_code = instance.group_code
|
|
|
+ object_id = instance.id
|
|
|
+ try:
|
|
|
+ self.perform_destroy(instance)
|
|
|
+ log_success_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"删除库位组成功,库位组编码: {group_code}",
|
|
|
+ operation_level="delete",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=object_id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
+ except Exception as e:
|
|
|
+ log_failure_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"删除库位组失败,库位组编码: {group_code}, 错误: {str(e)}",
|
|
|
+ operation_level="delete",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=object_id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ raise
|
|
|
|
|
|
def update(self, request, *args, **kwargs):
|
|
|
data = self.request.data
|
|
|
@@ -332,7 +461,30 @@ class locationGroupViewSet(viewsets.ModelViewSet):
|
|
|
if group_obj:
|
|
|
data['id'] = group_obj.id
|
|
|
logger.info(f"库位组 {group_code} 已存在")
|
|
|
-
|
|
|
+ # 更新现有库位组
|
|
|
+ serializer = LocationGroupPostSerializer(group_obj, data=data)
|
|
|
+ try:
|
|
|
+ serializer.is_valid(raise_exception=True)
|
|
|
+ serializer.save()
|
|
|
+ log_success_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"更新库位组成功,库位组编码: {group_code}",
|
|
|
+ operation_level="update",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=group_obj.id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ return Response(serializer.data, status=status.HTTP_200_OK)
|
|
|
+ except Exception as e:
|
|
|
+ log_failure_operation(
|
|
|
+ request=self.request,
|
|
|
+ operation_content=f"更新库位组失败,库位组编码: {group_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operator=self.request.auth.name if self.request.auth else None,
|
|
|
+ object_id=group_obj.id,
|
|
|
+ module_name="库位"
|
|
|
+ )
|
|
|
+ raise
|
|
|
else:
|
|
|
logger.info(f"库位组 {group_code} 不存在,创建库位组对象")
|
|
|
serializer_list = LocationGroupPostSerializer(data=data)
|
|
|
@@ -340,14 +492,14 @@ class locationGroupViewSet(viewsets.ModelViewSet):
|
|
|
serializer_list.save()
|
|
|
log_success_operation(
|
|
|
request=self.request,
|
|
|
- operation_content=f"创建库位组成功,库位组 {group_code} 已创建",
|
|
|
+ operation_content=f"创建库位组成功,库位组编码: {group_code}",
|
|
|
operation_level="new",
|
|
|
operator=self.request.auth.name if self.request.auth else None,
|
|
|
object_id=serializer_list.data.get('id'),
|
|
|
module_name="库位"
|
|
|
)
|
|
|
data['id'] = serializer_list.data.get('id')
|
|
|
- return Response(data, status=status.HTTP_201_CREATED)
|
|
|
+ return Response(data, status=status.HTTP_201_CREATED)
|
|
|
|
|
|
class LocationAllocation:
|
|
|
# 入库规则函数
|
|
|
@@ -450,11 +602,12 @@ class LocationAllocation:
|
|
|
return None
|
|
|
|
|
|
|
|
|
- def update_location_container_link(self,location_code,container_code):
|
|
|
+ def update_location_container_link(self,location_code,container_code, request=None):
|
|
|
"""
|
|
|
更新库位和托盘的关联关系
|
|
|
:param location_code: 库位编码
|
|
|
:param container_code: 托盘编码
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return:
|
|
|
"""
|
|
|
try:
|
|
|
@@ -473,15 +626,72 @@ class LocationAllocation:
|
|
|
)
|
|
|
location_container_link.save()
|
|
|
print(f"更新库位和托盘的关联关系成功!")
|
|
|
+ # 记录操作日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"创建库位-托盘关联,库位编码: {location_code}, 托盘编码: {container_code}",
|
|
|
+ operation_level="other",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"创建库位-托盘关联,库位编码: {location_code}, 托盘编码: {container_code}",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="success",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录库位-托盘关联日志失败: {str(log_error)}")
|
|
|
return True
|
|
|
# 3. 更新库位和托盘的关联关系
|
|
|
else:
|
|
|
LocationContainerLink.objects.filter(location=location).update(location=location, container=container)
|
|
|
print(f"更新库位和托盘的关联关系成功!")
|
|
|
+ # 记录操作日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新库位-托盘关联,库位编码: {location_code}, 托盘编码: {container_code}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新库位-托盘关联,库位编码: {location_code}, 托盘编码: {container_code}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="success",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录库位-托盘关联日志失败: {str(log_error)}")
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新库位和托盘的关联关系失败:{str(e)}")
|
|
|
print(f"更新库位和托盘的关联关系失败:{str(e)}")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新库位-托盘关联失败,库位编码: {location_code}, 托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新库位-托盘关联失败,库位编码: {location_code}, 托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录失败日志失败: {str(log_error)}")
|
|
|
return False
|
|
|
def update_container_detail_status(self,container_code,status):
|
|
|
try:
|
|
|
@@ -536,11 +746,12 @@ class LocationAllocation:
|
|
|
logger.error(f"更新库位组的批次失败:{str(e)}")
|
|
|
print(f"更新库位组的批次失败:{str(e)}")
|
|
|
return False
|
|
|
- def update_location_status(self,location_code,status):
|
|
|
+ def update_location_status(self,location_code,status, request=None):
|
|
|
"""
|
|
|
更新库位状态
|
|
|
:param location_code: 库位编码
|
|
|
:param status: 库位状态
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return:
|
|
|
"""
|
|
|
try:
|
|
|
@@ -552,22 +763,65 @@ class LocationAllocation:
|
|
|
print(f"库位获取失败!")
|
|
|
return False
|
|
|
# 2. 更新库位状态
|
|
|
+ old_status = location.status
|
|
|
location.status = status
|
|
|
location.save()
|
|
|
print(f"更新库位状态成功!")
|
|
|
+ # 记录操作日志(状态变更敏感操作)
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新库位状态,库位编码: {location_code}, 状态: {old_status} -> {status}",
|
|
|
+ operation_level="update",
|
|
|
+ object_id=str(location.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新库位状态,库位编码: {location_code}, 状态: {old_status} -> {status}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="success",
|
|
|
+ object_id=str(location.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录库位状态更新日志失败: {str(log_error)}")
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新库位状态失败:{str(e)}")
|
|
|
print(f"更新库位状态失败:{str(e)}")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新库位状态失败,库位编码: {location_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新库位状态失败,库位编码: {location_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录失败日志失败: {str(log_error)}")
|
|
|
return False
|
|
|
|
|
|
- def update_group_status_reserved(self,location_group_list):
|
|
|
+ def update_group_status_reserved(self,location_group_list, request=None):
|
|
|
"""
|
|
|
- 更新库位组状态
|
|
|
+ 更新库位组状态为预留
|
|
|
:param location_group_list: 库位组对象列表
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return:
|
|
|
"""
|
|
|
try:
|
|
|
+ reserved_groups = []
|
|
|
for location_group in location_group_list:
|
|
|
# 1. 获取库位组
|
|
|
if not location_group:
|
|
|
@@ -582,13 +836,54 @@ class LocationAllocation:
|
|
|
print(f"库位组 {location_group} 不存在")
|
|
|
return False
|
|
|
# 3. 更新库位组状态
|
|
|
+ old_status = location_group_item.status
|
|
|
location_group_item.status = 'reserved'
|
|
|
location_group_item.save()
|
|
|
+ reserved_groups.append(f"{location_group_item.group_code}({old_status}->reserved)")
|
|
|
+
|
|
|
+ # 记录预留库位组操作日志(敏感操作)
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"预留库位组,共{len(reserved_groups)}个: {', '.join(reserved_groups)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"预留库位组,共{len(reserved_groups)}个: {', '.join(reserved_groups)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="success",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录预留库位组日志失败: {str(log_error)}")
|
|
|
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新库位组状态失败:{str(e)}")
|
|
|
print(f"更新库位组状态失败:{str(e)}")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"预留库位组失败,错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"预留库位组失败,错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录失败日志失败: {str(log_error)}")
|
|
|
return False
|
|
|
|
|
|
def update_location_group_status(self, location_code):
|
|
|
@@ -636,11 +931,12 @@ class LocationAllocation:
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新库位组状态失败:{str(e)}")
|
|
|
print(f"更新库位组状态失败:{str(e)}")
|
|
|
- def update_batch_status(self,container_code,status):
|
|
|
+ def update_batch_status(self,container_code,status, request=None):
|
|
|
"""
|
|
|
更新批次状态
|
|
|
- :param batch_id: 批次id
|
|
|
+ :param container_code: 托盘编码
|
|
|
:param status: 批次状态
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return:
|
|
|
"""
|
|
|
try:
|
|
|
@@ -664,14 +960,55 @@ class LocationAllocation:
|
|
|
|
|
|
# 3. 更新批次状态
|
|
|
batch = container_detail.batch
|
|
|
+ old_status = batch.status
|
|
|
batch.status = status
|
|
|
batch.save()
|
|
|
|
|
|
print(f"更新批次状态成功!")
|
|
|
+ # 记录操作日志(批次状态变更敏感操作)
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新批次状态,托盘编码: {container_code}, 批次号: {batch.bound_number}, 状态: {old_status} -> {status}",
|
|
|
+ operation_level="update",
|
|
|
+ object_id=str(batch.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新批次状态,托盘编码: {container_code}, 批次号: {batch.bound_number}, 状态: {old_status} -> {status}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="success",
|
|
|
+ object_id=str(batch.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录批次状态更新日志失败: {str(log_error)}")
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
logger.error(f"更新批次状态失败:{str(e)}")
|
|
|
print(f"更新批次状态失败:{str(e)}")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"更新批次状态失败,托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"更新批次状态失败,托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录失败日志失败: {str(log_error)}")
|
|
|
return False
|
|
|
|
|
|
# def update_batch_goods_in_location_qty(self,container_code,taskworking):
|
|
|
@@ -816,21 +1153,52 @@ class LocationAllocation:
|
|
|
self.update_current_finish_task(container_code,current_task)
|
|
|
return location_list[0]
|
|
|
|
|
|
- def get_location_type(self, container_code):
|
|
|
+ def get_location_type(self, container_code, request=None):
|
|
|
"""
|
|
|
智能库位分配核心算法
|
|
|
:param container_code: 托盘码
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return: 库位类型分配方案
|
|
|
"""
|
|
|
try:
|
|
|
batch = self.get_batch(container_code)
|
|
|
if not batch:
|
|
|
logger.error("批次信息获取失败")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配算法执行失败,托盘编码: {container_code}, 错误: 批次信息获取失败",
|
|
|
+ operation_level="other",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配算法执行失败,托盘编码: {container_code}, 错误: 批次信息获取失败",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录算法失败日志失败: {str(log_error)}")
|
|
|
return None
|
|
|
|
|
|
# 检查已有分配方案
|
|
|
existing_solution = alloction_pre.objects.filter(batch_number=batch).first()
|
|
|
if existing_solution:
|
|
|
+ # 记录使用已有分配方案
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"使用已有库位分配方案,托盘编码: {container_code}, 批次号: {batch}",
|
|
|
+ operation_level="view",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录使用已有方案日志失败: {str(log_error)}")
|
|
|
return existing_solution.layer_pre_type
|
|
|
|
|
|
# 获取关键参数
|
|
|
@@ -914,6 +1282,25 @@ class LocationAllocation:
|
|
|
|
|
|
if not allocation:
|
|
|
logger.error("无法生成有效分配方案")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配算法执行失败,托盘编码: {container_code}, 批次号: {batch}, 托盘数: {total_pallets}, 错误: 无法生成有效分配方案",
|
|
|
+ operation_level="other",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配算法执行失败,托盘编码: {container_code}, 批次号: {batch}, 托盘数: {total_pallets}, 错误: 无法生成有效分配方案",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录算法失败日志失败: {str(log_error)}")
|
|
|
return None
|
|
|
|
|
|
# 保存分配方案
|
|
|
@@ -938,11 +1325,50 @@ class LocationAllocation:
|
|
|
solution.save()
|
|
|
solution_pressure.save()
|
|
|
|
|
|
+ # 记录算法执行成功日志(关键操作)
|
|
|
+ try:
|
|
|
+ allocation_summary = f"批次号: {batch}, 托盘数: {total_pallets}, 分配方案: {len(allocation[0])}个库位组, 压力分布: L1={allocation[1][0]}, L2={allocation[1][1]}, L3={allocation[1][2]}"
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配算法执行成功,托盘编码: {container_code}, {allocation_summary}",
|
|
|
+ operation_level="other",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配算法执行成功,托盘编码: {container_code}, {allocation_summary}",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="success",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录算法成功日志失败: {str(log_error)}")
|
|
|
|
|
|
return [loc.split('_')[1] for loc in allocation[0]]
|
|
|
|
|
|
except Exception as e:
|
|
|
logger.error(f"分配算法异常:{str(e)}")
|
|
|
+ # 记录异常日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配算法执行异常,托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="other",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配算法执行异常,托盘编码: {container_code}, 错误: {str(e)}",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录算法异常日志失败: {str(log_error)}")
|
|
|
return None
|
|
|
|
|
|
|
|
|
@@ -1071,11 +1497,12 @@ class LocationAllocation:
|
|
|
|
|
|
|
|
|
|
|
|
- def get_location_by_status(self,container_code,start_location):
|
|
|
+ def get_location_by_status(self,container_code,start_location, request=None):
|
|
|
"""
|
|
|
根据库位状态获取库位
|
|
|
- :param location_type: 库位类型
|
|
|
+ :param container_code: 托盘编码
|
|
|
:param start_location: 起始库位 if in1 优先考虑left_priority, if in2 优先考虑right_priority 就是获取库位组列表之后进行排序
|
|
|
+ :param request: 请求对象(可选)
|
|
|
:return: 库位列表
|
|
|
"""
|
|
|
# 1. 获取批次状态 1 为已组盘 2 为部分入库 3 为全部入库
|
|
|
@@ -1086,20 +1513,35 @@ class LocationAllocation:
|
|
|
print(f"[1]第一次入库")
|
|
|
|
|
|
# 重新获取最新数据
|
|
|
- self.get_location_type(container_code)
|
|
|
+ self.get_location_type(container_code, request)
|
|
|
|
|
|
location_type_list = json.loads(alloction_pre.objects.filter(batch_number=self.get_batch(container_code)).first().layer_pre_type)
|
|
|
location_list = self.get_location_by_type(location_type_list,start_location,container_code)
|
|
|
# 预定这些库组
|
|
|
- self.update_group_status_reserved(location_list)
|
|
|
+ self.update_group_status_reserved(location_list, request)
|
|
|
location_min_value = self.get_location_list_remainder(location_list,container_code)
|
|
|
print(f"库位安排到第{location_min_value.c_number}个库位:{location_min_value}")
|
|
|
- # if not location_list[location_min_index]:
|
|
|
- # # 库位已满,返回None
|
|
|
- # return None
|
|
|
- # else:
|
|
|
-
|
|
|
- # return location_list[location_min_index]
|
|
|
+ # 记录库位分配成功日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配成功(第一次入库),托盘编码: {container_code}, 起始位置: {start_location}, 分配库位: {location_min_value.location_code}, 库位组: {location_min_value.location_group}",
|
|
|
+ operation_level="other",
|
|
|
+ object_id=str(location_min_value.id),
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配成功(第一次入库),托盘编码: {container_code}, 起始位置: {start_location}, 分配库位: {location_min_value.location_code}, 库位组: {location_min_value.location_group}",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="success",
|
|
|
+ object_id=str(location_min_value.id),
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录库位分配日志失败: {str(log_error)}")
|
|
|
return location_min_value
|
|
|
|
|
|
elif status == 2:
|
|
|
@@ -1108,28 +1550,93 @@ class LocationAllocation:
|
|
|
location_list = alloction_pre.objects.filter(batch_number=self.get_batch(container_code)).first().layer_solution_type
|
|
|
location_min_value = self.get_location_list_remainder(location_list,container_code)
|
|
|
print(f"库位安排到第{location_min_value.c_number}个库位:{location_min_value}")
|
|
|
+ # 记录库位分配成功日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"库位分配成功(部分入库),托盘编码: {container_code}, 分配库位: {location_min_value.location_code}, 库位组: {location_min_value.location_group}",
|
|
|
+ operation_level="other",
|
|
|
+ object_id=str(location_min_value.id),
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"库位分配成功(部分入库),托盘编码: {container_code}, 分配库位: {location_min_value.location_code}, 库位组: {location_min_value.location_group}",
|
|
|
+ operation_level="other",
|
|
|
+ operation_result="success",
|
|
|
+ object_id=str(location_min_value.id),
|
|
|
+ module_name="库位分配算法"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录库位分配日志失败: {str(log_error)}")
|
|
|
return location_min_value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
- def release_location(self, location_code):
|
|
|
- """释放库位并更新关联数据"""
|
|
|
- try:
|
|
|
- location = LocationModel.objects.get(location_code=location_code)
|
|
|
- links = LocationContainerLink.objects.filter(location=location, is_active=True).first()
|
|
|
- if not links:
|
|
|
- logger.error(f"库位{location_code}未关联托盘")
|
|
|
- return True
|
|
|
- print(f"释放库位: {location_code}, 关联托盘: {links.container_id}")
|
|
|
- # 解除关联并标记为非活跃
|
|
|
- links.is_active = False
|
|
|
- links.save()
|
|
|
+ def release_location(self, location_code, request=None):
|
|
|
+ """释放库位并更新关联数据"""
|
|
|
+ try:
|
|
|
+ location = LocationModel.objects.get(location_code=location_code)
|
|
|
+ links = LocationContainerLink.objects.filter(location=location, is_active=True).first()
|
|
|
+ if not links:
|
|
|
+ logger.error(f"库位{location_code}未关联托盘")
|
|
|
return True
|
|
|
- except Exception as e:
|
|
|
- logger.error(f"释放库位失败: {str(e)}")
|
|
|
- return False
|
|
|
+ container_id = links.container_id
|
|
|
+ print(f"释放库位: {location_code}, 关联托盘: {container_id}")
|
|
|
+ # 解除关联并标记为非活跃
|
|
|
+ links.is_active = False
|
|
|
+ links.save()
|
|
|
+ # 更新库位状态为可用
|
|
|
+ location.status = 'available'
|
|
|
+ location.save()
|
|
|
+ # 记录释放库位操作日志(敏感操作)
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_success_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"释放库位,库位编码: {location_code}, 托盘ID: {container_id}",
|
|
|
+ operation_level="update",
|
|
|
+ object_id=str(location.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"释放库位,库位编码: {location_code}, 托盘ID: {container_id}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="success",
|
|
|
+ object_id=str(location.id),
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录释放库位日志失败: {str(log_error)}")
|
|
|
+ return True
|
|
|
+ except Exception as e:
|
|
|
+ logger.error(f"释放库位失败: {str(e)}")
|
|
|
+ # 记录失败日志
|
|
|
+ try:
|
|
|
+ if request:
|
|
|
+ log_failure_operation(
|
|
|
+ request=request,
|
|
|
+ operation_content=f"释放库位失败,库位编码: {location_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ else:
|
|
|
+ OperationLog.objects.create(
|
|
|
+ operator="系统自动",
|
|
|
+ operation_content=f"释放库位失败,库位编码: {location_code}, 错误: {str(e)}",
|
|
|
+ operation_level="update",
|
|
|
+ operation_result="failure",
|
|
|
+ module_name="库位分配"
|
|
|
+ )
|
|
|
+ except Exception as log_error:
|
|
|
+ logger.error(f"记录失败日志失败: {str(log_error)}")
|
|
|
+ return False
|
|
|
|
|
|
|
|
|
|