소스 검색

出库任务初步完成

flower_mr 1 개월 전
부모
커밋
eda0d5ab90
24개의 변경된 파일688개의 추가작업 그리고 71개의 파일을 삭제
  1. BIN
      container/__pycache__/models.cpython-38.pyc
  2. BIN
      container/__pycache__/views.cpython-38.pyc
  3. 23 0
      container/migrations/0002_containerwcsmodel_task_order_and_more.py
  4. 37 0
      container/migrations/0003_alter_containerwcsmodel_options_and_more.py
  5. 18 0
      container/migrations/0004_alter_containerwcsmodel_sequence.py
  6. 26 0
      container/migrations/0005_containerwcsmodel_batch_and_more.py
  7. 26 0
      container/migrations/0006_containerwcsmodel_batch_out_and_more.py
  8. 18 0
      container/migrations/0007_alter_containerwcsmodel_tasknumber.py
  9. 19 0
      container/migrations/0008_containerwcsmodel_order_number.py
  10. BIN
      container/migrations/__pycache__/0002_containerwcsmodel_task_order_and_more.cpython-38.pyc
  11. BIN
      container/migrations/__pycache__/0003_alter_containerwcsmodel_options_and_more.cpython-38.pyc
  12. BIN
      container/migrations/__pycache__/0004_alter_containerwcsmodel_sequence.cpython-38.pyc
  13. BIN
      container/migrations/__pycache__/0005_containerwcsmodel_batch_and_more.cpython-38.pyc
  14. BIN
      container/migrations/__pycache__/0006_containerwcsmodel_batch_out_and_more.cpython-38.pyc
  15. BIN
      container/migrations/__pycache__/0007_alter_containerwcsmodel_tasknumber.cpython-38.pyc
  16. BIN
      container/migrations/__pycache__/0008_containerwcsmodel_order_number.cpython-38.pyc
  17. 25 5
      container/models.py
  18. 261 56
      container/views.py
  19. 0 0
      data_base/generate_device.py
  20. 1 0
      data_base/init.ps1
  21. 10 10
      data_base/out_task.py
  22. BIN
      db.sqlite3
  23. 107 0
      logs/error.log
  24. 117 0
      logs/server.log

BIN
container/__pycache__/models.cpython-38.pyc


BIN
container/__pycache__/views.cpython-38.pyc


+ 23 - 0
container/migrations/0002_containerwcsmodel_task_order_and_more.py

@@ -0,0 +1,23 @@
+# Generated by Django 4.1.2 on 2025-04-25 22:42
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0001_initial'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='task_order',
+            field=models.IntegerField(default=0, verbose_name='任务顺序'),
+        ),
+        migrations.AlterField(
+            model_name='containerwcsmodel',
+            name='status',
+            field=models.IntegerField(choices=[(100, '等待中'), (200, '执行中'), (300, '已完成'), (400, '失败')], default=100, verbose_name='状态'),
+        ),
+    ]

+ 37 - 0
container/migrations/0003_alter_containerwcsmodel_options_and_more.py

@@ -0,0 +1,37 @@
+# Generated by Django 4.1.2 on 2025-04-25 23:12
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0002_containerwcsmodel_task_order_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name='containerwcsmodel',
+            options={'ordering': ['sequence'], 'verbose_name': 'ContainerWCS', 'verbose_name_plural': 'ContainerWCS'},
+        ),
+        migrations.RemoveField(
+            model_name='containerwcsmodel',
+            name='task_order',
+        ),
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='priority',
+            field=models.IntegerField(default=100, verbose_name='优先级'),
+        ),
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='sequence',
+            field=models.IntegerField(default=1, verbose_name='任务顺序'),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='containerwcsmodel',
+            name='status',
+            field=models.IntegerField(choices=[(100, '等待中'), (200, '已发送'), (300, '已完成'), (400, '失败')], default=100, verbose_name='状态'),
+        ),
+    ]

+ 18 - 0
container/migrations/0004_alter_containerwcsmodel_sequence.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-04-25 23:48
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0003_alter_containerwcsmodel_options_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='containerwcsmodel',
+            name='sequence',
+            field=models.BigIntegerField(verbose_name='任务顺序'),
+        ),
+    ]

+ 26 - 0
container/migrations/0005_containerwcsmodel_batch_and_more.py

@@ -0,0 +1,26 @@
+# Generated by Django 4.1.2 on 2025-04-26 10:19
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0001_initial'),
+        ('container', '0004_alter_containerwcsmodel_sequence'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='batch',
+            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='bound.boundbatchmodel', verbose_name='关联批次'),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='containerwcsmodel',
+            name='status',
+            field=models.IntegerField(choices=[(100, '等待中'), (101, '处理中'), (102, '已暂停'), (103, '入库中'), (200, '已发送'), (300, '已完成'), (400, '失败')], default=100, verbose_name='状态'),
+        ),
+    ]

+ 26 - 0
container/migrations/0006_containerwcsmodel_batch_out_and_more.py

@@ -0,0 +1,26 @@
+# Generated by Django 4.1.2 on 2025-04-26 14:12
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0001_initial'),
+        ('container', '0005_containerwcsmodel_batch_and_more'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='batch_out',
+            field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='bound.outbatchmodel', verbose_name='出库批次'),
+        ),
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='bound_list',
+            field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='bound.boundlistmodel', verbose_name='关联出库单'),
+            preserve_default=False,
+        ),
+    ]

+ 18 - 0
container/migrations/0007_alter_containerwcsmodel_tasknumber.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-04-26 14:56
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0006_containerwcsmodel_batch_out_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='containerwcsmodel',
+            name='tasknumber',
+            field=models.IntegerField(unique=True, verbose_name='任务号'),
+        ),
+    ]

+ 19 - 0
container/migrations/0008_containerwcsmodel_order_number.py

@@ -0,0 +1,19 @@
+# Generated by Django 4.1.2 on 2025-04-26 15:52
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0007_alter_containerwcsmodel_tasknumber'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='containerwcsmodel',
+            name='order_number',
+            field=models.IntegerField(default=1, verbose_name='c_number'),
+            preserve_default=False,
+        ),
+    ]

BIN
container/migrations/__pycache__/0002_containerwcsmodel_task_order_and_more.cpython-38.pyc


BIN
container/migrations/__pycache__/0003_alter_containerwcsmodel_options_and_more.cpython-38.pyc


BIN
container/migrations/__pycache__/0004_alter_containerwcsmodel_sequence.cpython-38.pyc


BIN
container/migrations/__pycache__/0005_containerwcsmodel_batch_and_more.cpython-38.pyc


BIN
container/migrations/__pycache__/0006_containerwcsmodel_batch_out_and_more.cpython-38.pyc


BIN
container/migrations/__pycache__/0007_alter_containerwcsmodel_tasknumber.cpython-38.pyc


BIN
container/migrations/__pycache__/0008_containerwcsmodel_order_number.cpython-38.pyc


+ 25 - 5
container/models.py

@@ -1,5 +1,6 @@
 from django.db import models
-from bound.models import BoundBatchModel,BoundDetailModel
+from bound.models import BoundBatchModel,BoundDetailModel,OutBatchModel,BoundListModel
+
 
 # Create your models here.
 # 主表:托盘数据
@@ -29,7 +30,8 @@ class ContainerDetailModel(models.Model):
     BATCH_STATUS=(
         (0, '空盘'),
         (1, '组盘'),
-        (2, '已出库')
+        (2, '在库'),
+        (3, '已出库')
     )
     month = models.IntegerField(verbose_name='月份')
     container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, related_name='details')
@@ -83,15 +85,31 @@ class ContainerOperationModel(models.Model):
         ordering = ['-timestamp']
 
 class ContainerWCSModel(models.Model):
+    TASK_STATUS = (
+        (100, '等待中'),
+        (101, '处理中'),
+        (102, '已暂停'),
+        (103, '入库中'),
+        (200, '已发送'),
+        (300, '已完成'),
+        (400, '失败'),
+    )
     taskid = models.CharField(max_length=50, verbose_name='任务ID')
+    batch = models.ForeignKey(BoundBatchModel, on_delete=models.CASCADE, verbose_name='关联批次')
+    batch_out = models.ForeignKey(OutBatchModel, on_delete=models.CASCADE, verbose_name='出库批次' ,  null=True, blank=True  )
+    bound_list = models.ForeignKey(BoundListModel, on_delete=models.CASCADE, verbose_name='关联出库单')
+    sequence = models.BigIntegerField(verbose_name='任务顺序')
+    priority = models.IntegerField(default=100, verbose_name='优先级')
     month = models.IntegerField(verbose_name='月份')
     tasktype = models.CharField(max_length=50, verbose_name='任务类型')
-    tasknumber = models.IntegerField(verbose_name='任务号')
+    tasknumber = models.IntegerField(verbose_name='任务号',unique=True)
+    order_number = models.IntegerField(verbose_name='c_number')
     container = models.CharField(max_length=50, verbose_name='托盘号')
     current_location = models.CharField(max_length=50, verbose_name='当前库位')
     target_location = models.CharField(max_length=50, verbose_name='目标库位')
     message = models.TextField(verbose_name='消息')
-    status = models.IntegerField(verbose_name='状态')
+    working = models.IntegerField(default = 1,verbose_name='工作状态')
+    status = models.IntegerField(choices=TASK_STATUS, default=100, verbose_name='状态')
 
     create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
     is_delete = models.BooleanField(default=False, verbose_name='是否删除')
@@ -100,7 +118,7 @@ class ContainerWCSModel(models.Model):
         db_table = 'container_wcs'
         verbose_name = 'ContainerWCS'
         verbose_name_plural = "ContainerWCS"
-        ordering = ['-create_time']
+        ordering = ['sequence']
     
     def to_dict(self):
         return {
@@ -115,6 +133,8 @@ class ContainerWCSModel(models.Model):
             'container': self.container,
             'status': self.status
         }
+    def __str__(self):
+        return f"{self.taskid} - {self.get_status_display()}"
 # 这里的批次详情是主入库申请单下的子批次
 class TaskModel(models.Model):
     

+ 261 - 56
container/views.py

@@ -29,7 +29,8 @@ from .filter import ContainerDetailFilter,ContainerListFilter,ContainerOperation
 from warehouse.models import ListModel as warehouse
 from staff.models import ListModel as staff
 from rest_framework.permissions import AllowAny
-
+import threading
+from django.db import close_old_connections
 logger = logging.getLogger(__name__)
 class ContainerListViewSet(viewsets.ModelViewSet):
     """
@@ -275,7 +276,8 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
                             + f"{int(location_list_cnumber.col):02d}" + '-' 
                             + f"{int(location_list_cnumber.layer):02d}" 
                         )
-                    self.generate_task(container, current_location, allocation_target_location)  # 生成任务
+                    batch_id = LocationAllocation.get_batch(container_code)
+                    self.generate_task(container, current_location, allocation_target_location,batch_id,location_list_cnumber.c_number)  # 生成任务
                     current_task = ContainerWCSModel.objects.get(
                         container=container, 
                         tasktype='inbound'
@@ -302,9 +304,20 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
             )
 
     @transaction.atomic
-    def generate_task(self, container, current_location, target_location):
+    def generate_task(self, container, current_location, target_location,batch_id,location_c_number):
+        batch = BoundBatchModel.objects.filter(bound_number=batch_id).first()
+        batch_detail = BoundDetailModel.objects.filter(bound_batch=batch).first()
+        if not batch:
+            logger.error(f"批次号 {batch_id} 不存在")
+            return False
         data_tosave = {
             'container': container,
+            'batch': batch,
+            'batch_out': None,
+            'bound_list': batch_detail.bound_list,
+            'sequence': 1,
+            'order_number' :location_c_number,
+            'priority': 1,
             'current_location': current_location,
             'month': timezone.now().strftime('%Y%m'),
             'target_location': target_location,  
@@ -335,6 +348,9 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
         data = self.request.data
         container = data.get('container_number')
         current_location = data.get('current_location')
+        taskNumber = data.get('taskNumber')
+    
+
         logger.info(f"请求托盘:{container},请求位置:{current_location}")
         if current_location =="203":
             current_location ="in1"
@@ -462,7 +478,8 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
                             + f"{int(location_list_cnumber.col):02d}" + '-' 
                             + f"{int(location_list_cnumber.layer):02d}" 
                         )
-                    self.generate_task(container, current_location, allocation_target_location)  # 生成任务
+                    batch_id = allocator.get_batch(container_code)
+                    self.generate_task(container, current_location, allocation_target_location,batch_id,location_list_cnumber.c_number)  # 生成任务
                     current_task = ContainerWCSModel.objects.get(
                         container=container, 
                         tasktype='inbound'
@@ -793,6 +810,219 @@ class ContainerOperateViewSet(viewsets.ModelViewSet):
         headers = self.get_success_headers(serializer.data)
         return Response(serializer.data, status=200, headers=headers)
 
+
+class OutboundService:
+    @staticmethod
+    def generate_task_id():
+        """生成唯一任务ID(格式: outbound-年月-顺序号)"""
+        month = timezone.now().strftime("%Y%m")
+        last_task = ContainerWCSModel.objects.filter(
+            tasktype='outbound', 
+            month=int(month)
+        ).order_by('-sequence').first()
+        sequence = last_task.sequence + 1 if last_task else 1
+        return f"outbound-{month}-{sequence:04d}"
+
+    # @staticmethod
+    # def send_task_to_wcs(task):
+    #     """发送任务到WCS"""
+    #     send_data = {
+    #         "taskid": task.taskid,
+    #         "container": task.container,
+    #         "current_location": task.current_location,
+    #         "target_location": task.target_location,
+    #         "tasktype": task.tasktype,
+    #         "month": task.month,
+    #         "message": task.message,
+    #         "status": task.status,
+    #         "taskNumber": task.tasknumber
+    #     }
+    #     try:
+    #         requests.post("http://127.0.0.1:8008/container/batch/", json=send_data, timeout=10)
+    #         response = requests.post("http://192.168.18.67:1616//wcs/WebApi/getOutTask", json=send_data, timeout=10)
+    #         if response.status_code == 200:
+    #             task.status = 200
+    #             task.save()/wcs/WebApi/getOutTask
+    #             logger.info(f"任务 {task.taskid} 已发送")
+    #             return True
+    #         else:
+    #             logger.error(f"WCS返回错误: {response.text}")
+    #             task.status = 400
+    #             task.save()
+    #             return False
+    #     except Exception as e:
+    #         logger.error(f"发送失败: {str(e)}")
+     
+
+    #    return False
+
+    @staticmethod
+    def send_task_to_wcs(task):
+        """异步发送任务到WCS(非阻塞版本)"""
+        # 提取任务关键数据用于线程(避免直接传递ORM对象)
+        task_data = {
+            'task_id': task.pk,  # 使用主键而不是对象
+            'send_data': {
+            "code":'200',
+            "message": task.message,
+            "data":{
+                "taskid": task.taskid,
+                "container": task.container,
+                "current_location": task.current_location,
+                "target_location": task.target_location,
+                "tasktype": task.tasktype,
+                "month": task.month,
+                "message": task.message,
+                "status": task.status,
+                "taskNumber": task.tasknumber,
+                "order_number":task.order_number,
+                "sequence":task.sequence
+            }
+            }
+        }
+        
+        # 创建并启动线程
+        thread = threading.Thread(
+            target=OutboundService._async_send_handler,
+            kwargs=task_data,
+            daemon=True  # 守护线程(主程序退出时自动终止)
+        )
+        thread.start()
+        return True  # 立即返回表示已开始处理
+
+    @staticmethod
+    def _async_send_handler(task_id, send_data):
+        """异步处理的实际工作函数"""
+        try:
+            # 每个线程需要独立的数据库连接
+            close_old_connections()
+            
+            # 重新获取任务对象(确保使用最新数据)
+            task = ContainerWCSModel.objects.get(pk=task_id)
+            
+            # 发送第一个请求(不处理结果)
+            requests.post(
+                "http://127.0.0.1:8008/container/batch/",
+                json=send_data,
+                timeout=10
+            )
+            
+            # 发送关键请求
+            response = requests.post(
+                "http://192.168.18.67:1616/wcs/WebApi/getOutTask",
+                json=send_data,
+                timeout=10
+            )
+            
+            # 处理响应
+            if response.status_code == 200:
+                task.status = 200
+                task.save()
+                logger.info(f"任务 {task.taskid} 已发送")
+            else:
+                logger.error(f"WCS返回错误: {response.text}")
+
+                
+        except Exception as e:
+            logger.error(f"发送失败: {str(e)}")
+
+        finally:
+            close_old_connections()  # 清理数据库连接
+
+    @staticmethod
+    def create_initial_tasks(container_list,bound_list_id):
+        """生成初始任务队列"""
+        with transaction.atomic():
+            current_WCS = ContainerWCSModel.objects.filter(tasktype='outbound',bound_list_id = bound_list_id).first()
+            if current_WCS:
+                logger.error(f"当前{bound_list_id}已有出库任务")
+          
+                return False
+            tasks = []
+            start_sequence = ContainerWCSModel.objects.filter(tasktype='outbound').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
+                OutBoundDetail_obj = OutBoundDetailModel.objects.filter(bound_list=bound_list_id,bound_batch_number_id=container['batch_id']).first()
+                if not OutBoundDetail_obj:
+                    logger.error(f"批次 {container['batch_id']} 不存在")
+                    return False
+                month = int(timezone.now().strftime("%Y%m"))
+                task = ContainerWCSModel(
+                    taskid=OutboundService.generate_task_id(),
+                    batch = OutBoundDetail_obj.bound_batch_number,
+                    batch_out = OutBoundDetail_obj.bound_batch,
+                    bound_list = OutBoundDetail_obj.bound_list,
+                    sequence=index,
+                    order_number = container['location_c_number'],
+                    priority=100,
+                    tasknumber = month*10000+tasknumber_index+tasknumber,
+                    container=container_obj.container_code,
+                    current_location=container_obj.current_location,
+                    target_location="103",
+                    tasktype="outbound",
+                    month=int(timezone.now().strftime("%Y%m")),
+                    message="等待出库",
+                    status=100,
+                )
+                tasknumber_index += 1
+                tasks.append(task)
+            ContainerWCSModel.objects.bulk_create(tasks)
+            logger.info(f"已创建 {len(tasks)} 个初始任务")
+
+    @staticmethod
+    def insert_new_tasks(new_tasks):
+        """动态插入新任务并重新排序"""
+        with transaction.atomic():
+            pending_tasks = list(ContainerWCSModel.objects.select_for_update().filter(status=100))
+            
+            # 插入新任务
+            for new_task_data in new_tasks:
+                new_task = ContainerWCSModel(
+                    taskid=OutboundService.generate_task_id(),
+                    priority=new_task_data.get('priority', 100),
+                    container=new_task_data['container'],
+                    current_location=new_task_data['current_location'],
+                    target_location=new_task_data.get('target_location', 'OUT01'),
+                    tasktype="outbound",
+                    month=int(timezone.now().strftime("%Y%m")),
+                    message="等待出库",
+                    status=100,
+                )
+                # 找到插入位置
+                insert_pos = 0
+                for i, task in enumerate(pending_tasks):
+                    if new_task.priority < task.priority:
+                        insert_pos = i
+                        break
+                else:
+                    insert_pos = len(pending_tasks)
+                pending_tasks.insert(insert_pos, new_task)
+            
+            # 重新分配顺序号
+            for i, task in enumerate(pending_tasks, start=1):
+                task.sequence = i
+                if task.pk is None:
+                    task.save()
+                else:
+                    task.save(update_fields=['sequence'])
+            
+            logger.info(f"已插入 {len(new_tasks)} 个新任务")
+
+    @staticmethod
+    def process_next_task():
+        """处理下一个任务"""
+        next_task = ContainerWCSModel.objects.filter(status=100).order_by('sequence').first()
+        if not next_task:
+            logger.info("没有待处理任务")
+            return
+        OutboundService.send_task_to_wcs(next_task)
+
+
 class OutTaskViewSet(viewsets.ModelViewSet):
 
     """
@@ -807,27 +1037,35 @@ class OutTaskViewSet(viewsets.ModelViewSet):
         try:
             data = self.request.data
             logger.info(f"收到 WMS 推送数据: {data}")
-            send_data= {
-                "container": "12345",
-                "current_location": "in1",
-                "month": 202503,
-                "current_location": "W01-01-01-01",
-                "target_location": "W01-01-01-01",
-                "tasktype": "inbound",
-                "taskid": "inbound-202503-0001",
-                "message": "生成入库任务",
-                "status": 103
-            }
-            post_json_to_url("http://127.0.0.1:8008/container/batch/", send_data)
+            
+            # 假设从请求中获取 bound_list_id
+            bound_list_id = data.get('bound_list_id')
+            batch_count = self.get_batch_count_by_boundlist(bound_list_id)
+            
+            logger.info(f"出库批次数量: {batch_count}")
+            # 获取需要出库的托盘列表
+            generate_result = self.generate_location_by_demand(batch_count)
+            if generate_result['code'] != '200':
+                return Response(generate_result, status=500)
+            container_list = generate_result['data']
+            
+            logger.info(f"生成出库任务: {container_list}")
+            #  2. 生成初始任务
+            OutboundService.create_initial_tasks(container_list,bound_list_id)
+            
+            # 3. 立即发送第一个任务
+            OutboundService.process_next_task()
+            
             return Response({"code": "200", "msg": "Success"}, status=200)
         except Exception as e:
+            logger.error(f"任务生成失败: {str(e)}")
             return Response({"code": "500", "msg": str(e)}, status=500)
 
     def get_batch_count_by_boundlist(self,bound_list_id):
         try:
             bound_list_obj_all = OutBoundDetailModel.objects.filter(bound_list=bound_list_id).all()
             if bound_list_obj_all:
-                logger.info(f"查询批次数量成功: {bound_list_obj_all.count()}")
+            
                 batch_count_dict = {}
                 # 统计批次数量(创建哈希表,去重)
                 for batch in bound_list_obj_all:
@@ -843,12 +1081,11 @@ class OutTaskViewSet(viewsets.ModelViewSet):
             logger.error(f"查询批次数量失败: {str(e)}")
             return {}
 
-
     def get_location_by_status_and_batch(self,status,bound_id):
         try:
             container_obj = ContainerDetailModel.objects.filter(batch=bound_id,status=status).all()
             if container_obj:
-                logger.info(f"查询{status}状态的批次数量成功: {container_obj.count()}")
+              
                 container_dict = {}
                 # 统计托盘数量(创建哈希表,去重)
                 for obj in container_obj:
@@ -863,7 +1100,8 @@ class OutTaskViewSet(viewsets.ModelViewSet):
         except Exception as e:
             logger.error(f"查询{status}状态的批次数量失败: {str(e)}")
             return {}
-    def get_order_by_batch(self,container_list):
+    
+    def get_order_by_batch(self,container_list,bound_id):
         try:
             container_dict = {}
             for container in container_list:
@@ -875,7 +1113,8 @@ class OutTaskViewSet(viewsets.ModelViewSet):
                             "container_number":container,
                             "location_c_number":location_c_number,
                             "location_id ":location_container.location.id,
-                            "location_type":location_container.location.location_type
+                            "location_type":location_container.location.location_type,
+                            "batch_id":bound_id,
                             }
 
             if len(container_dict.keys()) == len(container_list):
@@ -901,7 +1140,7 @@ class OutTaskViewSet(viewsets.ModelViewSet):
                 if not container_list:
                     return {"code": "500", "msg": f"批次 {demand_id} 不存在"}
                 container_id_list = container_list.keys()
-                container_order = self.get_order_by_batch(container_id_list) 
+                container_order = self.get_order_by_batch(container_id_list,demand_id) 
                 if not container_order:
                     return {"code": "500", "msg": f"托盘 {container_id_list} 不存在"}
                 order = sorted(
@@ -940,37 +1179,3 @@ class BatchViewSet(viewsets.ModelViewSet):
         logger.info(f"收到 WMS 推送数据: {data}")
         return Response({"code": "200", "msg": "Success"}, status=200)
 
-def post_json_to_url(url, data):
-    """
-    发送 JSON 数据到指定 URL
-    :param url: 目标地址 (e.g., "https://api.example.com/endpoint")
-    :param data: 要发送的字典数据 (e.g., {"key": "value"})
-    :return: 响应内容 (字典) 或错误信息
-    """
-    headers = {
-        'Content-Type': 'application/json',
-        # 可选:添加认证头 (如 Token)
-        # 'Authorization': f'Bearer {settings.API_TOKEN}'
-    }
-
-    try:
-        # 发送 POST 请求
-        response = requests.post(
-            url,
-            data=json.dumps(data),  # 序列化为 JSON 字符串
-            headers=headers,
-            timeout=10  # 超时时间(秒)
-        )
-
-        # 检查 HTTP 状态码
-        response.raise_for_status()
-
-        # 解析 JSON 响应
-        return response.json()
-
-    except requests.exceptions.RequestException as e:
-        # 处理网络错误、超时等
-        return {"error": str(e)}
-    except json.JSONDecodeError:
-        # 处理响应非 JSON 格式的情况
-        return {"error": "Invalid JSON response"}

data_base/generate_location_group copy.py → data_base/generate_device.py


+ 1 - 0
data_base/init.ps1

@@ -1,6 +1,7 @@
 python generate_warehouse.py
 python generate_location.py
 python generate_location_group.py
+python generate_device.py
 python import_data.py
 python import_product.py
 

+ 10 - 10
data_base/out_task.py

@@ -28,16 +28,16 @@ def main():
 
     testtask = OutTaskViewSet()
 
-    count =testtask.get_batch_count_by_boundlist("2")
-    if not count:
-        print("❌ 批次下没有可用的库位,请检查批次号")
-        return
-    print(f"[1]批次下可用的库位数:{count}")
-    location_demand = testtask.generate_location_by_demand(count)
-    if not location_demand:
-        print("❌ 库位需求生成失败,请检查托盘编码")
-        return
-    print(f"[2]库位需求:{location_demand}")
+    # count =testtask.get_batch_count_by_boundlist("2")
+    # if not count:
+    #     print("❌ 批次下没有可用的库位,请检查批次号")
+    #     return
+    # print(f"[1]批次下可用的库位数:{count}")
+    # location_demand = testtask.generate_location_by_demand(count)
+    # if not location_demand:
+    #     print("❌ 库位需求生成失败,请检查托盘编码")
+    #     return
+    # print(f"[2]库位需求:{location_demand}")
     # for demand_id, demand_qty in count.items():
     #     print (f"需求{demand_id}的库位数:{demand_qty}")
 

BIN
db.sqlite3


+ 107 - 0
logs/error.log

@@ -4449,3 +4449,110 @@ Traceback (most recent call last):
   File "D:\Document\code\vue\greater_wms\.\utils\throttle.py", line 18, in allow_request
     openid = request.auth.openid
 AttributeError: 'NoneType' object has no attribute 'openid'
+[2025-04-25 23:13:11,610][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:15:16,591][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:17:08,375][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:17:15,548][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 511, in dispatch
+    self.response = self.finalize_response(request, response, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 423, in finalize_response
+    assert isinstance(response, HttpResponseBase), (
+AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'NoneType'>`
+[2025-04-25 23:23:45,601][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:27:41,874][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:29:04,180][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 10:40:34,776][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 10:44:37,668][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 10:45:25,910][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 14:14:39,827][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:14:45,760][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:24:03,961][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:59:01,580][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:00:36,161][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:01:37,060][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:21:46,106][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:34:09,887][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:56:19,143][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 16:00:49,383][django.request.log_response():241] [ERROR] Internal Server Error: /bound/outdetail/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "D:\Document\code\vue\greater_wms\.\bound\views.py", line 382, in create
+    data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
+KeyError: 'bound_batch'
+[2025-04-26 16:06:46,012][django.request.log_response():241] [ERROR] Internal Server Error: /bound/outdetail/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "D:\Document\code\vue\greater_wms\.\bound\views.py", line 382, in create
+    data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
+KeyError: 'bound_batch'
+[2025-04-26 16:07:34,758][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 16:19:50,735][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/

+ 117 - 0
logs/server.log

@@ -6589,3 +6589,120 @@ AttributeError: 'NoneType' object has no attribute 'openid'
 [2025-04-25 00:18:09,431][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
 [2025-04-25 13:39:35,238][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
 [2025-04-25 14:47:56,577][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-25 20:53:47,983][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-25 23:13:11,610][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:15:16,591][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:17:08,375][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:17:15,548][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 511, in dispatch
+    self.response = self.finalize_response(request, response, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 423, in finalize_response
+    assert isinstance(response, HttpResponseBase), (
+AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'NoneType'>`
+[2025-04-25 23:23:45,601][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:27:41,874][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-25 23:29:04,180][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 10:30:35,895][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 10:40:34,776][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 10:44:37,668][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 10:45:25,910][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 10:51:09,691][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 14:14:39,827][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:14:45,760][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:24:03,961][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 14:59:01,580][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:00:36,161][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:01:37,060][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:16:20,767][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 15:21:46,106][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:24:34,647][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 15:34:09,887][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 15:53:32,592][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 15:53:37,686][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 15:56:08,164][django.request.log_response():241] [WARNING] Bad Request: /container/container_wcs/update/
+[2025-04-26 15:56:19,143][django.request.log_response():241] [ERROR] Internal Server Error: /container/container_wcs/update/
+[2025-04-26 15:58:15,203][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 16:00:49,383][django.request.log_response():241] [ERROR] Internal Server Error: /bound/outdetail/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "D:\Document\code\vue\greater_wms\.\bound\views.py", line 382, in create
+    data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
+KeyError: 'bound_batch'
+[2025-04-26 16:06:46,012][django.request.log_response():241] [ERROR] Internal Server Error: /bound/outdetail/
+Traceback (most recent call last):
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 472, in thread_handler
+    raise exc_info[1]
+  File "d:\language\python38\lib\site-packages\django\core\handlers\exception.py", line 42, in inner
+    response = await get_response(request)
+  File "d:\language\python38\lib\site-packages\django\core\handlers\base.py", line 253, in _get_response_async
+    response = await wrapped_callback(
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 435, in __call__
+    ret = await asyncio.wait_for(future, timeout=None)
+  File "d:\language\python38\lib\asyncio\tasks.py", line 455, in wait_for
+    return await fut
+  File "d:\language\python38\lib\concurrent\futures\thread.py", line 57, in run
+    result = self.fn(*self.args, **self.kwargs)
+  File "d:\language\python38\lib\site-packages\asgiref\sync.py", line 476, in thread_handler
+    return func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
+    return view_func(*args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\viewsets.py", line 125, in view
+    return self.dispatch(request, *args, **kwargs)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 509, in dispatch
+    response = self.handle_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 469, in handle_exception
+    self.raise_uncaught_exception(exc)
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
+    raise exc
+  File "d:\language\python38\lib\site-packages\rest_framework\views.py", line 506, in dispatch
+    response = handler(request, *args, **kwargs)
+  File "D:\Document\code\vue\greater_wms\.\bound\views.py", line 382, in create
+    data['bound_batch_number'] = OutBatchModel.objects.get(id=data['bound_batch']).batch_number.id
+KeyError: 'bound_batch'
+[2025-04-26 16:07:21,879][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-26 16:07:34,758][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/
+[2025-04-26 16:19:50,735][django.request.log_response():241] [ERROR] Internal Server Error: /container/out_task/