| 
															
																@@ -1,5 +1,5 @@ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 from wsgiref import headers 
															 | 
															
															 | 
															
																 from wsgiref import headers 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-from rest_framework.views import APIView 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+from rest_framework.viewsets import ViewSet 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 from rest_framework import viewsets 
															 | 
															
															 | 
															
																 from rest_framework import viewsets 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 from utils.page import MyPageNumberPagination 
															 | 
															
															 | 
															
																 from utils.page import MyPageNumberPagination 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 from django.db.models import Prefetch  
															 | 
															
															 | 
															
																 from django.db.models import Prefetch  
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -886,6 +886,13 @@ class ContainerWCSViewSet(viewsets.ModelViewSet): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																                 return Response({'code': '500', 'message': '出库状态更新失败', 'data': None}, 
															 | 
															
															 | 
															
																                 return Response({'code': '500', 'message': '出库状态更新失败', 'data': None}, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																                                 status=status.HTTP_500_INTERNAL_SERVER_ERROR) 
															 | 
															
															 | 
															
																                                 status=status.HTTP_500_INTERNAL_SERVER_ERROR) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             OutboundService.process_next_task() 
															 | 
															
															 | 
															
																             OutboundService.process_next_task() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        if task and task.tasktype == 'check' and task.status == 300: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            success = self.handle_outbound_completion(container_obj, task) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if not success: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return Response({'code': '500', 'message': '出库状态更新失败', 'data': None}, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                                status=status.HTTP_500_INTERNAL_SERVER_ERROR) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            OutboundService.process_next_task() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																          
															 | 
															
															 | 
															
																          
															 | 
														
													
												
													
														
															| 
															 | 
															
																         return Response({ 
															 | 
															
															 | 
															
																         return Response({ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             'code': '200', 
															 | 
															
															 | 
															
																             'code': '200', 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1084,32 +1091,35 @@ class ContainerWCSViewSet(viewsets.ModelViewSet): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         try: 
															 | 
															
															 | 
															
																         try: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             allocator = LocationAllocation() 
															 | 
															
															 | 
															
																             allocator = LocationAllocation() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             location_task = task.current_location 
															 | 
															
															 | 
															
																             location_task = task.current_location 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            location_row = location_task.split('-')[1] 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            location_col = location_task.split('-')[2] 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            location_layer = location_task.split('-')[3] 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            location= LocationModel.objects.filter(row=location_row, col=location_col, layer=location_layer).first() 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            location_code = location.location_code 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-   
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if location_task == '103' or location_task == '203': 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return True 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            else: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                location_row = location_task.split('-')[1] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                location_col = location_task.split('-')[2] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                location_layer = location_task.split('-')[3] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                location= LocationModel.objects.filter(row=location_row, col=location_col, layer=location_layer).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                location_code = location.location_code 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+     
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            # 事务确保原子性 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            with transaction.atomic(): 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                # 解除库位与托盘的关联 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                if not allocator.release_location(location_code): 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                    raise Exception("解除库位关联失败") 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                # 事务确保原子性 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                with transaction.atomic(): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # 解除库位与托盘的关联 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    if not allocator.release_location(location_code): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                        raise Exception("解除库位关联失败") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                # 更新库位状态为可用 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                if not allocator.update_location_status(location_code, 'available'): 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                    raise Exception("库位状态更新失败") 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # 更新库位状态为可用 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    if not allocator.update_location_status(location_code, 'available'): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                        raise Exception("库位状态更新失败") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                # 更新库位组的统计信息 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                self.handle_group_location_status(location_code, location.location_group) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # 更新库位组的统计信息 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    self.handle_group_location_status(location_code, location.location_group) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                # 更新托盘状态为已出库(假设状态3表示已出库) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                container_obj.status = 3 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                container_obj.save() 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # 更新托盘状态为已出库(假设状态3表示已出库) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    container_obj.status = 3 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    container_obj.save() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            return True 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return True 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         except Exception as e: 
															 | 
															
															 | 
															
																         except Exception as e: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             logger.error(f"出库完成处理失败: {str(e)}") 
															 | 
															
															 | 
															
																             logger.error(f"出库完成处理失败: {str(e)}") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             return False 
															 | 
															
															 | 
															
																             return False 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1680,6 +1690,50 @@ class OutboundService: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																                 container_obj.save() 
															 | 
															
															 | 
															
																                 container_obj.save() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             ContainerWCSModel.objects.bulk_create(tasks) 
															 | 
															
															 | 
															
																             ContainerWCSModel.objects.bulk_create(tasks) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             logger.info(f"已创建 {len(tasks)} 个初始任务") 
															 | 
															
															 | 
															
																             logger.info(f"已创建 {len(tasks)} 个初始任务") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+     
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+    @staticmethod 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+    def create_initial_check_tasks(container_list,batch_id): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        """生成初始任务队列""" 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        with transaction.atomic(): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            current_WCS = ContainerWCSModel.objects.filter(tasktype='check',batch_id = batch_id,is_delete=False,working=1).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if current_WCS: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                logger.error(f"当前{batch_id}已有检查任务") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return False 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            tasks = [] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            start_sequence = ContainerWCSModel.objects.filter(tasktype='check').count() + 1 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            tasknumber = ContainerWCSModel.objects.filter().count()  
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            tasknumber_index = 1 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            for index, container in enumerate(container_list, start=start_sequence): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_obj = ContainerListModel.objects.filter(id =container['container_number']).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                if container_obj.current_location != container_obj.target_location: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    logger.error(f"托盘 {container_obj.container_code} 未到达目的地,不生成任务") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    return False 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                batch_obj = BoundBatchModel.objects.filter(id =batch_id).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                month = int(timezone.now().strftime("%Y%m")) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                task = ContainerWCSModel( 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    taskid=OutboundService.generate_task_id(), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    batch = batch_obj, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    batch_out = None, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    bound_list = None, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    sequence=index, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    order_number = container['c_number'], 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    priority=100, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    tasknumber = month*100000+tasknumber_index+tasknumber, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    container=container_obj.container_code, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    current_location=container_obj.current_location, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    target_location="103", 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    tasktype="check", 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    month=int(timezone.now().strftime("%Y%m")), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    message="等待出库", 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    status=100, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                tasknumber_index += 1 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                tasks.append(task) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_obj = ContainerListModel.objects.filter(container_code=task.container).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_obj.target_location = task.target_location 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_obj.save() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            ContainerWCSModel.objects.bulk_create(tasks) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            logger.info(f"已创建 {len(tasks)} 个初始任务") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																     @staticmethod 
															 | 
															
															 | 
															
																     @staticmethod 
															 | 
														
													
												
													
														
															| 
															 | 
															
																     def insert_new_tasks(new_tasks): 
															 | 
															
															 | 
															
																     def insert_new_tasks(new_tasks): 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1775,7 +1829,7 @@ class OutboundService: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																 # 出库任务下发 
															 | 
															
															 | 
															
																 # 出库任务下发 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-class OutTaskViewSet(APIView): 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+class OutTaskViewSet(ViewSet): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																     """ 
															 | 
															
															 | 
															
																     """ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																     # fun:get_out_task:下发出库任务 
															 | 
															
															 | 
															
																     # fun:get_out_task:下发出库任务 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1799,9 +1853,9 @@ class OutTaskViewSet(APIView): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																                 if current_WCS.working == 1: 
															 | 
															
															 | 
															
																                 if current_WCS.working == 1: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																                     OutboundService.process_current_task(current_WCS.taskid) 
															 | 
															
															 | 
															
																                     OutboundService.process_current_task(current_WCS.taskid) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                    return Response({"code": "200", "msg": f"下发任务{ current_WCS.taskid }到WCS成功"}, status=200) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    return Response({"code": 200, "msg": f"下发任务{ current_WCS.taskid }到WCS成功"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																                 else : 
															 | 
															
															 | 
															
																                 else : 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                    return Response({"code": "200", "msg": f"当前任务{current_WCS.taskid}正在处理中"}, status=200) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    return Response({"code": 200, "msg": f"当前任务{current_WCS.taskid}正在处理中"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1812,7 +1866,7 @@ class OutTaskViewSet(APIView): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             ).select_related('batch_number') 
															 | 
															
															 | 
															
																             ).select_related('batch_number') 
															 | 
														
													
												
													
														
															| 
															 | 
															
																              
															 | 
															
															 | 
															
																              
															 | 
														
													
												
													
														
															| 
															 | 
															
																             if not out_batches.exists(): 
															 | 
															
															 | 
															
																             if not out_batches.exists(): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-                return Response({"code": "404", "msg": "未找到相关出库批次"}, status=404) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return Response({"code": 404, "msg": "未找到相关出库批次"}, status=404) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             # 构建批次需求字典 
															 | 
															
															 | 
															
																             # 构建批次需求字典 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             batch_demand = {} 
															 | 
															
															 | 
															
																             batch_demand = {} 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             for ob in out_batches: 
															 | 
															
															 | 
															
																             for ob in out_batches: 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1846,14 +1900,43 @@ class OutTaskViewSet(APIView): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             # 3. 立即发送第一个任务 
															 | 
															
															 | 
															
																             # 3. 立即发送第一个任务 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             OutboundService.process_next_task() 
															 | 
															
															 | 
															
																             OutboundService.process_next_task() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																              
															 | 
															
															 | 
															
																              
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            return Response({"code": "200", "msg": "Success"}, status=200) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return Response({"code": 200, "msg": "下发任务成功"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         except Exception as e: 
															 | 
															
															 | 
															
																         except Exception as e: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             logger.error(f"任务生成失败: {str(e)}") 
															 | 
															
															 | 
															
																             logger.error(f"任务生成失败: {str(e)}") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-            return Response({"code": "200", "msg": str(e)}, status=200) 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return Response({"code": 200, "msg": str(e)}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																  
															 | 
															
															 | 
															
																  
															 | 
														
													
												
													
														
															| 
															 | 
															
																- 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-    # 获取出库需求 
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+    def post_check(self, request): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        try: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            data = self.request.data 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            logger.info(f"收到 出库抽检 推送数据: {data}") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 从请求中获取 batch_id 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            batch_id = data.get('batch_id') 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            container_demand = int(data.get('container_demand')) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if not batch_id or not container_demand: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return Response({"code": "400", "msg": "缺少抽检数目或批次号"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            current_WCS = ContainerWCSModel.objects.filter(batch=batch_id,tasktype='check',is_delete=False,working=1).first() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if current_WCS: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                logger.info(f"当前{batch_id}已有出库抽检任务{current_WCS.taskid}") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                if current_WCS.working == 1: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    OutboundService.process_current_task(current_WCS.taskid) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    return Response({"code": 200, "msg": f"下发任务{ current_WCS.taskid }到WCS成功"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                else : 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    return Response({"code": 200, "msg": f"当前任务{current_WCS.taskid}正在处理中"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 获取批次号 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            generate_result = self.generate_location_by_check(batch_id,container_demand) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            if generate_result['code'] != '200': 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return Response(generate_result, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 创建并处理出库任务 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            container_list = generate_result['data'] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 3. 立即发送第一个任务 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            OutboundService.create_initial_check_tasks(container_list,batch_id) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            OutboundService.process_next_task() 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return Response({"code": 200, "msg": "下发任务成功"}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        except Exception as e: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            logger.error(f"任务生成失败: {str(e)}") 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return Response({"code": 200, "msg": str(e)}, status=200) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+         
															 | 
														
													
												
													
														
															| 
															 | 
															
																     def get_batch_count_by_boundlist(self,bound_list_id): 
															 | 
															
															 | 
															
																     def get_batch_count_by_boundlist(self,bound_list_id): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         try: 
															 | 
															
															 | 
															
																         try: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             bound_list_obj_all = OutBoundDetailModel.objects.filter(bound_list=bound_list_id).all() 
															 | 
															
															 | 
															
																             bound_list_obj_all = OutBoundDetailModel.objects.filter(bound_list=bound_list_id).all() 
															 | 
														
													
												
											
												
													
														
															 | 
															
																@@ -1946,7 +2029,75 @@ class OutTaskViewSet(APIView): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             ) 
															 | 
															
															 | 
															
																             ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             .order_by('container_id', '-id') 
															 | 
															
															 | 
															
																             .order_by('container_id', '-id') 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         ) 
															 | 
															
															 | 
															
																         ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																-         
															 | 
															
															 | 
															
																 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+    def generate_location_by_check(self,batch_id,container_demand): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        ''' 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        根据抽检托盘数目,把相应的库位给到出库任务 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        ''' 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        try: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return_data = [] 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 获取已去重的托盘列表 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            container_qs = self.get_container_allocation(batch_id) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+             
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 构建托盘信息字典(自动去重) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            container_map = {} 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            for cd in container_qs: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                if cd.container_id in container_map: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    continue 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                # 获取有效库位信息 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                active_location = next( 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    (link.location for link in cd.container.active_location  
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                        if link.is_active), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                        None 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_map[cd.container_id] = { 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    'detail': cd, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    'container': cd.container, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    'location': active_location 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                } 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                # 转换为排序列表 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            container_list = list(container_map.values()) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+             
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            sorted_containers = sorted( 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_list, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                key=lambda x: ( 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    self._get_goods_class_priority(x['detail'].goods_class), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    -(x['location'].c_number if x['location'] else 0), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # -(x['location'].layer if x['location'] else 0), 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # x['location'].row if x['location'] else 0, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    # x['location'].col if x['location'] else 0 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            ) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            for item in sorted_containers: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                if container_demand <= 0: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                   break 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                # 获取可分配数量 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                # 记录分配信息 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                allocate_container = { 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    "container_number": item['container'].id, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    "batch_id": batch_id, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    "location_code": item['location'].location_code if item['location'] else 'N/A', 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    "allocate_qty": 0, 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                    "c_number": item['location'].c_number if item['location'] else 0 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                } 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                return_data.append(allocate_container)   
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+                container_demand -= 1 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 降重 return_data,以container_number为key 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return_data = list({v['container_number']: v for v in return_data}.values()) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+             
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            # 排序 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return_data = sorted(return_data, key=lambda x: -x['c_number']) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return {"code": "200", "msg": "Success", "data": return_data} 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+        except Exception as e: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            logger.error(f"出库任务生成失败: {str(e)}", exc_info=True) 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+            return {"code": "500", "msg": str(e)} 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																 
															 | 
															
															 | 
															
																+ 
															 | 
														
													
												
													
														
															| 
															 | 
															
																     def generate_location_by_demand(self, batch_demand, bound_list_id): 
															 | 
															
															 | 
															
																     def generate_location_by_demand(self, batch_demand, bound_list_id): 
															 | 
														
													
												
													
														
															| 
															 | 
															
																         try: 
															 | 
															
															 | 
															
																         try: 
															 | 
														
													
												
													
														
															| 
															 | 
															
																             return_data = [] 
															 | 
															
															 | 
															
																             return_data = [] 
															 |