Kaynağa Gözat

入库函数完善

flower_mr 1 ay önce
ebeveyn
işleme
e34ca9627f

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


BIN
bin/__pycache__/serializers.cpython-38.pyc


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


+ 29 - 0
bin/migrations/0006_alter_locationcontainerlink_unique_together_and_more.py

@@ -0,0 +1,29 @@
+# Generated by Django 4.1.2 on 2025-04-17 14:09
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0001_initial'),
+        ('bin', '0005_alter_locationgroupmodel_status'),
+    ]
+
+    operations = [
+        migrations.AlterUniqueTogether(
+            name='locationcontainerlink',
+            unique_together=set(),
+        ),
+        migrations.AlterField(
+            model_name='locationcontainerlink',
+            name='container',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='container.containerlistmodel', unique=True),
+        ),
+        migrations.AlterField(
+            model_name='locationcontainerlink',
+            name='location',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bin.locationmodel', unique=True, verbose_name='库位'),
+        ),
+    ]

+ 29 - 0
bin/migrations/0007_alter_locationcontainerlink_container_and_more.py

@@ -0,0 +1,29 @@
+# Generated by Django 4.1.2 on 2025-04-17 15:41
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0001_initial'),
+        ('bin', '0006_alter_locationcontainerlink_unique_together_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='locationcontainerlink',
+            name='container',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='container.containerlistmodel'),
+        ),
+        migrations.AlterField(
+            model_name='locationcontainerlink',
+            name='location',
+            field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='bin.locationmodel', verbose_name='库位'),
+        ),
+        migrations.AlterUniqueTogether(
+            name='locationcontainerlink',
+            unique_together={('location', 'container')},
+        ),
+    ]

+ 18 - 0
bin/migrations/0008_alter_locationmodel_current_quantity.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-04-17 20:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bin', '0007_alter_locationcontainerlink_container_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='locationmodel',
+            name='current_quantity',
+            field=models.PositiveIntegerField(default=0, verbose_name='当前数'),
+        ),
+    ]

BIN
bin/migrations/__pycache__/0006_alter_locationcontainerlink_unique_together_and_more.cpython-38.pyc


BIN
bin/migrations/__pycache__/0007_alter_locationcontainerlink_container_and_more.cpython-38.pyc


BIN
bin/migrations/__pycache__/0008_alter_locationmodel_current_quantity.cpython-38.pyc


+ 48 - 9
bin/models.py

@@ -41,7 +41,7 @@ class LocationModel(models.Model):
     location_type = models.CharField(max_length=3, choices=LOCATION_TYPES, verbose_name='货位类型')
     status = models.CharField(max_length=20, choices=LOCATION_STATUS, default='available', verbose_name='库位状态')
     max_capacity = models.PositiveIntegerField(verbose_name='最大容量')  # 根据类型自动设置
-    current_quantity = models.PositiveIntegerField(default=0, verbose_name='当前托盘数')
+    current_quantity = models.PositiveIntegerField(default=0, verbose_name='当前数')
     c_number = models.IntegerField(default=1, verbose_name='库位远近排序')
     current_containers = models.ManyToManyField(ContainerListModel, 
                                               through='LocationContainerLink',
@@ -860,15 +860,10 @@ class LocationGroupModel(models.Model):
                         group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
                         group_item.save()
         
-
-        
-
-    
-
 # 库位-托盘关联表(记录实时存放关系)
 class LocationContainerLink(models.Model):
-    location = models.ForeignKey(LocationModel, on_delete=models.CASCADE,unique=True, verbose_name='库位')
-    container = models.ForeignKey(ContainerListModel, unique=True,on_delete=models.CASCADE)
+    location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位')
+    container = models.ForeignKey(ContainerListModel,on_delete=models.CASCADE)
     task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True)
     task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True)
     put_time = models.DateTimeField(auto_now_add=True, verbose_name='上架时间')
@@ -879,9 +874,9 @@ class LocationContainerLink(models.Model):
         verbose_name = 'Location-Container Link'
         verbose_name_plural = "Location-Container Link"
         ordering = ['-id']
+        unique_together = ( 'location', 'container')  # 防止重复关联
   
 
-
 class DeviceModel(models.Model):
     location = models.ForeignKey(LocationModel, on_delete=models.CASCADE)
     device_id = models.CharField(max_length=255, verbose_name="Device ID")
@@ -925,3 +920,47 @@ class LocationChangeLog(models.Model):
         verbose_name = 'Location Change Log'
         verbose_name_plural = "Location Change Log"
         ordering = ['-id']
+
+class alloction_pre(models.Model):
+
+    batch_number = models.CharField(max_length=255, verbose_name='批次号')
+    layer1_pre = models.IntegerField(default=0, verbose_name='第一层预留')
+    layer2_pre = models.IntegerField(default=0, verbose_name='第二层预留')
+    layer3_pre = models.IntegerField(default=0, verbose_name='第三层预留')
+
+    layer1_pre_type = models.JSONField(default=list, verbose_name='第一层预留类型')
+    layer1_pre_type_number = models.JSONField(default=list, verbose_name='第一层预留数目')
+    layer2_pre_type = models.JSONField(default=list, verbose_name='第二层预留')
+    layer2_pre_type_number = models.JSONField(default=list, verbose_name='第二层预留数目')
+    layer3_pre_type = models.JSONField(default=list, verbose_name='第三层预留')
+    layer3_pre_type_number = models.JSONField(default=list, verbose_name='第三层预留数目')
+ 
+    layer1_pressure = models.IntegerField(default=0, verbose_name='第一层工作压力')
+    layer2_pressure = models.IntegerField(default=0, verbose_name='第二层工作压力')
+    layer3_pressure = models.IntegerField(default=0, verbose_name='第三层工作压力')
+
+    create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
+    class Meta:
+        db_table = 'allocation_pre'
+        verbose_name = 'Allocation_pre'
+        verbose_name_plural = "Allocation_pre"
+        ordering = ['-id']
+
+class allocation_history(models.Model):
+    location = models.ForeignKey(LocationModel, on_delete=models.CASCADE, verbose_name='库位')
+    container = models.ForeignKey(ContainerListModel, on_delete=models.CASCADE, verbose_name='托盘')
+    task_wcs = models.ForeignKey(ContainerWCSModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='WCS任务')
+    task_detail = models.ForeignKey(TaskModel, on_delete=models.CASCADE, null=True, blank=True, verbose_name='批次详情')
+    operation_type = models.CharField(max_length=10, verbose_name='操作类型')
+    related_location = models.ForeignKey(LocationModel, 
+                                       on_delete=models.SET_NULL,
+                                       null=True,
+                                       related_name='related_logs_history',
+                                       verbose_name='关联库位')  # 用于移库操作
+    timestamp = models.DateTimeField(auto_now_add=True, verbose_name='操作时间')
+
+    class Meta:
+        db_table = 'allocation_history'
+        verbose_name = 'Allocation_history'
+        verbose_name_plural = "Allocation_history"
+        ordering = ['-id']

+ 1 - 1
bin/serializers.py

@@ -17,7 +17,7 @@ class LocationPostSerializer(serializers.ModelSerializer):
     class Meta:
         model = LocationModel
         fields = '__all__'
-        read_only_fields = ['id','row','col','layer', 'max_capacity', 'current_quantity', 'coordinate','access_priority']
+        read_only_fields = ['id','row','col','layer', 'max_capacity', 'current_quantity', 'coordinate','access_priority','location_code','location_group','location_type','is_active','shelf_type']
 
 class LocationGroupSerializer(serializers.ModelSerializer):
     class Meta:

+ 481 - 222
bin/views.py

@@ -11,7 +11,7 @@ from django.utils import timezone
 from django.db import transaction
 import logging
 from rest_framework import status
-from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog
+from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog,alloction_pre
 from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
 
 
@@ -26,15 +26,189 @@ logger = logging.getLogger(__name__)
 # 库位分配
 # 入库规则函数
 # 逻辑根据批次下的托盘数目来找满足区间范围的库位,按照优先级排序,
+     
+
+class locationViewSet(viewsets.ModelViewSet):
+    """
+        retrieve:
+            Response a data list(get)
+            list:
+            Response a data list(all)
+        create:
+            Create a data line(post)
+
+        delete:
+            Delete a data line(delete)
+
+    """
+    # authentication_classes = []  # 禁用所有认证类
+    # permission_classes = [AllowAny]  # 允许任意访问
+    
+    pagination_class = MyPageNumberPagination   
+    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
+    ordering_fields = ['id', "create_time", "update_time", ]
+    filter_class = LocationFilter
+
+    def get_project(self):
+        try:
+            id = self.kwargs.get('pk')
+            return id
+        except:
+            return None
+
+    def get_queryset(self):
+        id = self.get_project()
+        if self.request.user:
+            if id is None:
+                return LocationModel.objects.filter()
+            else:
+                return LocationModel.objects.filter( id=id)
+        else:
+            return LocationModel.objects.none()
+    def get_serializer_class(self):
+        if self.action == 'list':
+            return LocationListSerializer
+        elif self.action == 'update':
+            return LocationPostSerializer
+        elif self.action =='retrieve':
+            return LocationListSerializer
+
+    def update(self, request, *args, **kwargs):
+        qs = self.get_object()
+        data = self.request.data
+
+        location_code = data.get('location_code')
+        # 处理库位对象
+        location_obj = LocationModel.objects.filter(location_code=location_code).first()
+        if not location_obj:
+            logger.info(f"库位 {location_code} 不存在")
+            return Response(
+                {'code': '400', 'message': '库位不存在', 'data': None},
+                status=status.HTTP_400_BAD_REQUEST
+            )
+        else:
+            data['id'] = location_obj.id
+            logger.info(f"库位 {location_code} 已存在")
+            serializer = self.get_serializer(qs, data=data)
+            serializer.is_valid(raise_exception=True)
+            serializer.save()
+            headers = self.get_success_headers(serializer.data)
+            self.handle_group_location_status(location_code,location_obj.location_group)
+            return Response(serializer.data, status=200, headers=headers)
+
+    def handle_group_location_status(self,location_code,location_group):
+        """
+        处理库位组和库位的关联关系
+        :param location_code: 库位编码
+        :param location_group: 库位组编码
+        :return:
+        """
+        # 1. 获取库位空闲状态的库位数目
+        location_obj_number = LocationModel.objects.filter(
+            location_group=location_group,
+            status='available'
+        ).all().count()
+        # 2. 获取库位组对象
+        logger.info(f"库位组 {location_group} 下的库位数目:{location_obj_number}")
+        # 1. 获取库位和库位组的关联关系
+        location_group_obj = LocationGroupModel.objects.filter(
+            group_code=location_group
+        ).first()
+        if not location_group_obj:
+            logger.info(f"库位组 {location_group} 不存在")
+            return None
+        else:
+            if location_obj_number == 0:
+                # 库位组库位已满,更新库位组状态为full
+                location_group_obj.status = 'full'
+                location_group_obj.save()
+            elif location_obj_number < location_group_obj.max_capacity:
+                location_group_obj.status = 'occupied'
+                location_group_obj.save()
+            else:
+                location_group_obj.status = 'available'
+                location_group_obj.save()
+       
+class locationGroupViewSet(viewsets.ModelViewSet):
+    """
+        retrieve:
+            Response a data list(get)
+            list:
+            Response a data list(all)
+        create:
+            Create a data line(post)
+
+        delete:
+            Delete a data line(delete)
+
+    """
+    # authentication_classes = []  # 禁用所有认证类
+    # permission_classes = [AllowAny]  # 允许任意访问
+    
+    pagination_class = MyPageNumberPagination   
+    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
+    ordering_fields = ['id', "create_time", "update_time", ]
+    filter_class = LocationGroupFilter
+
+    def get_project(self):
+        try:
+            id = self.kwargs.get('pk')
+            return id
+        except:
+            return None
+
+                           
+    def get_queryset(self):             
+        id = self.get_project()
+        if self.request.user:
+            if id is None:
+                return LocationGroupModel.objects.filter()  
+            else:
+                return LocationGroupModel.objects.filter(id=id)            
+        else:
+            return LocationGroupModel.objects.none()                           
+    def get_serializer_class(self):                                             
+        if self.action == 'list':
+            return LocationGroupListSerializer          
+
+        elif self.action == 'update':
+            return LocationGroupPostSerializer
+
+        elif self.action =='retrieve':
+            return LocationGroupListSerializer      
+    
+    def update(self, request, *args, **kwargs):
+        data = self.request.data
+        order_month = str(timezone.now().strftime('%Y%m'))
+        data['month'] = order_month
+        group_code = data.get('group_code')
+        # 处理库位组对象
+        group_obj = LocationGroupModel.objects.filter(group_code=group_code).first()
+        if group_obj:
+            data['id'] = group_obj.id
+            logger.info(f"库位组 {group_code} 已存在")
+        else:
+            logger.info(f"库位组 {group_code} 不存在,创建库位组对象")
+            serializer_list = LocationGroupPostSerializer(data=data)
+            serializer_list.is_valid(raise_exception=True)
+            serializer_list.save()
+            data['id'] = serializer_list.data.get('id')
+        return Response(data, status=status.HTTP_201_CREATED)
+
 class LocationAllocation:
     # 入库规则函数
     # fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
+    # fun:get_left_locationGroup_number_by_type: 获取每层库位组剩余数量
     # fun:get_location_type: 根据托盘数目获取库位类型
-    # fun:updata_location_container_link: 更新库位和托盘的关联关系
+    # fun:update_location_container_link: 更新库位和托盘的关联关系
+    # fun:update_location_group_batch: 更新库位组的批次
+    # fun:update_batch_status: 更新批次状态yes/no
+    # fun:update_location_status: 更新库位状态和
+    # fun:up
     # fun:get_batch_status: 获取批次状态
     # fun:get_batch: 获取批次
     # fun:get_location_list_remainder: 获取可用库位的c_number列表
-    # fun:get_min_list_index: 获取最小的库位
+
     # fun:get_location_by_type_remainder: 根据库位类型获取库位
     # fun:get_location_by_type: 第一次入库,根据库位类型获取库位
     # fun:get_location_by_status: 根据库位状态获取库位
@@ -66,29 +240,110 @@ class LocationAllocation:
             return None
         else:
             print (f"容器 {container_code} 已组盘")
-        batch_container_count = ContainerDetailModel.objects.filter(
+        batch_container = ContainerDetailModel.objects.filter(
              batch = container_detail.batch.id,
              status = 1
-        ).count()
-       
+        ).all()
+        # 统计批次下的不同托盘 item.contianer_id
+        batch_container_count = 0
+        container_ids = []
+        for item in batch_container:
+            if item.container_id not in container_ids: 
+                batch_container_count = batch_container_count + 1
+                container_ids.append(item.container_id)
+        batch_item = BoundBatchModel.objects.filter(  bound_number = container_detail.batch.bound_number).first()
+        if not batch_item:
+            print(f"批次号获取失败!")
+            return None
+        batch_item.container_number = batch_container_count
+        batch_item.save()
         return batch_container_count
     
-    def get_location_type(self,container_count):
-        """
-        根据托盘数目获取库位类型
-        :param container_count: 托盘数目
-        :return: 库位类型
-        """
-        if container_count <= 1:
-            return ["T1"]
-        elif container_count <= 2:
-            return ["T2"]
-        elif container_count <= 4:
-            return ["S4","T4"]
+    def get_left_locationGroup_number_by_type(self):
+        """
+        获取每层库位组剩余数量
+        :return:
+        """
+        try:
+            # 定义库位组和层号
+            group = ['T1', 'T2', 'S4', 'T4', 'T5']
+            layer = [1, 2, 3]
+            # 初始化结果列表,包含三个空字典对应三个层
+            left_number = [{} for _ in layer]
+            
+            for item in group:
+                for idx, layer_num in enumerate(layer):
+                    # 检查库位组是否存在(不考虑状态)
+                    exists = LocationGroupModel.objects.filter(
+                        group_type=item,
+                        layer=layer_num
+                    ).exists()
+                    
+                    if not exists:
+                        print(f"库位组 {item}_{layer_num} 不存在")
+                        left_number[idx][item] = 0
+                    else:
+                        # 统计可用状态的库位组数量
+                        count = LocationGroupModel.objects.filter(
+                            group_type=item,
+                            layer=layer_num,
+                            status='available'
+                        ).count()
+                        left_number[idx][item] = count
+                        
+            return left_number
+        except Exception as e:
+            logger.error(f"获取库位组剩余数量失败:{str(e)}")
+            print(f"获取库位组剩余数量失败:{str(e)}")
+            return None
+
+    def get_location_type(self,container_code):
+        """
+        :param container_code: 托盘码
+        :return: 库位类型列表
+        """
+        batch = self.get_batch(container_code)
+        if not batch:
+            print(f"类型分配中批次号获取失败!")
+            return None
+        location_solution = alloction_pre.objects.filter(batch_number=batch).first()
+        if not location_solution:
+            # 1. 获取托盘码对应批次号下所有的托盘数目
+            container_number = self.get_pallet_count_by_batch(container_code)
+            print (f"该批次下托盘总数:{container_number}")
+            # 2. 计算每层剩余的库位数目
+            layer_number=self.get_pallet_count_by_batch()
+            # 3. 查看最新库位分配方案
+            location_solution_last = alloction_pre.objects.filter().order_by('-id').first()
+            if not location_solution_last:
+                layer1_pressure =0
+                layer2_pressure =0
+                layer3_pressure =0
+            else:
+                layer1_pressure = location_solution_last.layer1_pressure
+                layer2_pressure = location_solution_last.layer2_pressure
+                layer3_pressure = location_solution_last.layer3_pressure
+            # 4. 根据工作压力和库位类型,使用贪心算法,(AGV只有两个库位,故只给考虑1 2 层工作压力,第三层仅作为1,2层的补充,不考虑压力)获取库位类型列表,完成任务之后更新压力/TODO:需要考虑库位类型和库位数量的关系
+            if layer1_pressure <=layer2_pressure:
+
+            print(f"库位类型:{location_type}")
+            # 5. 保存库位分配方案
+            alloction_pre.objects.create(
+                batch_number=batch,
+                layer1_pressure=layer1_pressure,
+                layer2_pressure=layer2_pressure,
+                layer3_pressure=layer3_pressure,
+
+                location_type=','.join(location_type)
+            )
+            return location_type
         else:
-            return ["T5"]
+            print(f"库位类型:{location_solution.location_type}")
+            return location_solution.location_type.split(",")
+
+        
     @transaction.atomic
-    def updata_location_container_link(self,location_code,container_code):
+    def update_location_container_link(self,location_code,container_code):
         """
         更新库位和托盘的关联关系
         :param location_code: 库位编码
@@ -111,6 +366,7 @@ class LocationAllocation:
                 )
                 location_container_link.save()
                 print(f"更新库位和托盘的关联关系成功!")
+                return True
             # 3. 更新库位和托盘的关联关系
             else:
                 LocationContainerLink.objects.filter(location=location).update(location=location, container=container)
@@ -120,6 +376,142 @@ class LocationAllocation:
             logger.error(f"更新库位和托盘的关联关系失败:{str(e)}")
             print(f"更新库位和托盘的关联关系失败:{str(e)}")
             return False    
+    def update_location_group_batch(self,location,container_code):
+        """
+        :param location: 库位对象
+        :param container_code: 托盘码
+
+        :return:
+        """
+        try:
+            # 1. 获取库位组
+            location_group = LocationGroupModel.objects.filter(
+                group_code=location.location_group
+            ).first()
+            if not location_group:
+                print(f"库位组获取失败!")
+                return False
+            # 2. 更新库位组的批次
+            bound_number=self.get_batch(container_code)
+            if not bound_number:
+                print(f"批次号获取失败!")
+                return False
+            location_group.current_batch = bound_number
+            location_group.save()
+            print(f"更新库位组的批次成功!")
+            return True
+        except Exception as e:       
+            logger.error(f"更新库位组的批次失败:{str(e)}")
+            print(f"更新库位组的批次失败:{str(e)}")
+            return False    
+    def update_location_status(self,location_code,status):
+        """
+        更新库位状态
+        :param location_code: 库位编码
+        :param status: 库位状态
+        :return:
+        """
+        try:
+            # 1. 获取库位
+            location = LocationModel.objects.filter(
+                location_code=location_code
+            ).first()
+            if not location:
+                print(f"库位获取失败!")
+                return False
+            # 2. 更新库位状态
+            location.status = status
+            location.save()
+            print(f"更新库位状态成功!")
+            return True
+        except Exception as e:       
+            logger.error(f"更新库位状态失败:{str(e)}")
+            print(f"更新库位状态失败:{str(e)}")
+            return False    
+    def update_location_group_status(self, location_code):
+        """
+        更新库位组状态
+        :param location_code: 库位编码
+        :return:
+        """
+        try:
+            # 1. 获取库位
+            location = LocationModel.objects.filter(
+                location_code=location_code
+            ).first()
+            if not location:
+                print(f"库位获取失败!")
+                return False
+            
+            # 2. 获取库位组
+            location_group = LocationGroupModel.objects.filter(
+                group_code=location.location_group
+            ).first()
+            if not location_group:
+                print(f"库位组获取失败!")
+                return False
+            current=0
+            for location_item in location_group.location_items.all():
+                if location_item.status != 'available':
+                    current=current + 1
+            # 3. 更新库位组状态
+            if current == 0:
+                location_group.status = 'available'
+            elif current == location_group.max_capacity:
+                location_group.status = 'full'
+            else:
+                location_group.status = 'occupied'
+            
+            location_group.current_goods_quantity = sum(
+                    [loc.current_quantity for loc in location_group.location_items.all()]
+                )
+            location_group.current_quantity = current
+                
+            location_group.save()
+            print(f"更新库位组状态成功!")
+            return True
+        except Exception as e:       
+            logger.error(f"更新库位组状态失败:{str(e)}")
+            print(f"更新库位组状态失败:{str(e)}")
+    def update_batch_status(self,container_code,status):
+        """
+        更新批次状态
+        :param batch_id: 批次id
+        :param status: 批次状态
+        :return:
+        """
+        try:
+            # 1. 通过托盘码获取容器详情
+            container = ContainerListModel.objects.filter(
+                container_code=container_code
+            ).first()
+
+            if not container:
+                logger.error(f"托盘 {container_code} 不存在")
+                print(f"托盘 {container_code} 不存在")
+                return None
+            # 2. 获取关联的批次明细
+            container_detail = ContainerDetailModel.objects.filter(
+                container=container.id,
+                status=1
+            ).first()
+            if not container_detail:
+                print (f"容器 {container_code} 未组盘")
+                logger.error(f"容器 {container_code} 未组盘")
+                return None
+            else:
+                print (f"容器 {container_code} 已组盘")
+            # 3. 更新批次状态
+            batch = container_detail.batch
+            batch.status = status
+            batch.save()
+            print(f"更新批次状态成功!")
+            return True
+        except Exception as e:       
+            logger.error(f"更新批次状态失败:{str(e)}")
+            print(f"更新批次状态失败:{str(e)}")
+            return False  
+
     def get_batch_status(self,container_code):
         """
         获取批次状态
@@ -185,28 +577,19 @@ class LocationAllocation:
         """
         if not location_list:
             return None
+        min_c_number=1000
+        min_c_number_index=1000
 
-        available_c_numbers = [
-            loc.c_number for loc in location_list 
-            if loc.status == 'available'
-        ]
-        
-        return available_c_numbers if available_c_numbers else None
-    def get_min_list_index(self,list):
-        """
-        获取最小的库位
-        :param list: 库位列表
-        :return: 最小库位
-        """
-        if not list:
+        for location in location_list:
+            if location.status != 'available':
+                continue
+            if int(location.c_number)<min_c_number:
+                min_c_number=int(location.c_number)
+                min_c_number_index=location_list.index(location)
+        if min_c_number_index==1000:
             return None
-        min_index = 0
-        for i in range(len(list)):
-            if list[i] < list[min_index]:
-                min_index = i
-        return min_index
-
-
+        else:  
+            return min_c_number_index
     @transaction.atomic
     def get_location_by_type_remainder(self, batch, layer):
         """
@@ -252,11 +635,8 @@ class LocationAllocation:
         else:
             ordered_groups = location_groups.none()
 
-        # 合并所有库位组中的库位
         locations = []
-    
         locations.extend(ordered_groups.first().location_items.all())  # 假设location_items是关联字段
-
         return locations if locations else None
     @transaction.atomic
     def get_location_by_status(self,container_code,start_location,layer):
@@ -273,199 +653,78 @@ class LocationAllocation:
         if status == 1:
             # 2. 获取库位组
             print (f"第一次入库")
-            container_number = self.get_pallet_count_by_batch(container_code)
-            print (f"该批次下托盘总数:{container_number}")
-            location_type_list = self.get_location_type(container_number)
+           
+            location_type_list = self.get_location_type(container_code)
             print(f"库位类型:{location_type_list}")
             location_list = self.get_location_by_type(location_type_list,start_location,layer)
             print(f"库位列表:{location_list}")
-            location_list_remainder = self.get_location_list_remainder(location_list)
-            print(f"库位列表剩余:{location_list_remainder}")
-            if not location_list_remainder:
+            location_min_index = self.get_location_list_remainder(location_list)
+            print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
+            if not location_list[location_min_index]:
                 # 库位已满,返回None
                 return None
             else:
-                location_index = self.get_min_list_index(location_list_remainder)
-                # 返回和托盘关联的库位、库位剩余、库位类型
-                return location_list[location_index]
+                
+                return location_list[location_min_index]
         elif status == 2:
             print(f"部分入库")
             # 2. 获取库位组
             location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
-            location_list_remainder = self.get_location_list_remainder(location_list)
-            if not location_list_remainder:
+            print(f"库位列表:{location_list}")
+            location_min_index = self.get_location_list_remainder(location_list)
+            print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
+            if not location_list[location_min_index]:
                 # 库位已满,返回None
                 return None
             else:
-                location_index = self.get_min_list_index(location_list_remainder)
-                # 返回和托盘关联的库位、库位剩余、库位类型
-                return location_list[location_index]
-         
-
-
-class locationViewSet(viewsets.ModelViewSet):
-    """
-        retrieve:
-            Response a data list(get)
-            list:
-            Response a data list(all)
-        create:
-            Create a data line(post)
-
-        delete:
-            Delete a data line(delete)
-
-    """
-    # authentication_classes = []  # 禁用所有认证类
-    # permission_classes = [AllowAny]  # 允许任意访问
-    
-    pagination_class = MyPageNumberPagination   
-    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
-    ordering_fields = ['id', "create_time", "update_time", ]
-    filter_class = LocationFilter
-
-    def get_project(self):
-        try:
-            id = self.kwargs.get('pk')
-            return id
-        except:
-            return None
-
-    def get_queryset(self):
-        id = self.get_project()
-        if self.request.user:
-            if id is None:
-                return LocationModel.objects.filter()
-            else:
-                return LocationModel.objects.filter( id=id)
-        else:
-            return LocationModel.objects.none()
-    def get_serializer_class(self):
-        if self.action == 'list':
-            return LocationListSerializer
-        elif self.action == 'update':
-            return LocationPostSerializer
-        elif self.action =='retrieve':
-            return LocationListSerializer
-
-    def update(self, request, *args, **kwargs):
-        qs = self.get_object()
-        data = self.request.data
-
-        location_code = data.get('location_code')
-        # 处理库位对象
-        location_obj = LocationModel.objects.filter(location_code=location_code).first()
-        if not location_obj:
-            logger.info(f"库位 {location_code} 不存在")
-            return Response(
-                {'code': '400', 'message': '库位不存在', 'data': None},
-                status=status.HTTP_400_BAD_REQUEST
-            )
-        else:
-            data['id'] = location_obj.id
-            logger.info(f"库位 {location_code} 已存在")
-            serializer = self.get_serializer(qs, data=data)
-            serializer.is_valid(raise_exception=True)
-            serializer.save()
-            headers = self.get_success_headers(serializer.data)
-            self.handle_group_location_status(location_code,location_obj.location_group)
-            return Response(serializer.data, status=200, headers=headers)
-
-    def handle_group_location_status(self,location_code,location_group):
+                return location_list[location_min_index]
+        elif status == 3:
+            print(f"全部入库")
+            # 2. 获取库位组
+            location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
+            return location_list
+            
+  
         """
-        处理库位组和库位的关联关系
-        :param location_code: 库位编码
-        :param location_group: 库位组编码
-        :return:
+        根据库位状态清除库位
+        :param container_code: 托盘码
+        :param start_location: 起始库位 if in1 优先考虑left_priority, if in2 优先考虑right_priority 就是获取库位组列表之后进行排序
+        :param layer: 层数 限定层数
+        :return: 库位列表
         """
-        # 1. 获取库位空闲状态的库位数目
-        location_obj_number = LocationModel.objects.filter(
-            location_group=location_group,
-            status='available'
-        ).all().count()
-        # 2. 获取库位组对象
-        logger.info(f"库位组 {location_group} 下的库位数目:{location_obj_number}")
-        # 1. 获取库位和库位组的关联关系
-        location_group_obj = LocationGroupModel.objects.filter(
-            group_code=location_group
-        ).first()
-        if not location_group_obj:
-            logger.info(f"库位组 {location_group} 不存在")
-            return None
-        else:
-            if location_obj_number == 0:
-                # 库位组库位已满,更新库位组状态为full
-                location_group_obj.status = 'full'
-                location_group_obj.save()
-            elif location_obj_number < location_group_obj.max_capacity:
-                location_group_obj.status = 'occupied'
-                location_group_obj.save()
+        # 1. 获取批次状态 102 为已组盘 103 为部分入库 104 为全部入库
+        status = self.get_batch_status(container_code)
+        # 
+        if status == 1:
+            # 2. 获取库位组
+            print (f"第一次入库")
+            container_number = self.get_pallet_count_by_batch(container_code)
+            print (f"该批次下托盘总数:{container_number}")
+            location_type_list = self.get_location_type(container_number)
+            print(f"库位类型:{location_type_list}")
+            location_list = self.get_location_by_type(location_type_list,start_location,layer)
+            print(f"库位列表:{location_list}")
+            location_min_index = self.get_location_list_remainder(location_list)
+            print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
+            if not location_list[location_min_index]:
+                # 库位已满,返回None
+                return None
             else:
-                location_group_obj.status = 'available'
-                location_group_obj.save()
-       
-class locationGroupViewSet(viewsets.ModelViewSet):
-    """
-        retrieve:
-            Response a data list(get)
-            list:
-            Response a data list(all)
-        create:
-            Create a data line(post)
-
-        delete:
-            Delete a data line(delete)
-
-    """
-    # authentication_classes = []  # 禁用所有认证类
-    # permission_classes = [AllowAny]  # 允许任意访问
-    
-    pagination_class = MyPageNumberPagination   
-    filter_backends = [DjangoFilterBackend, OrderingFilter, ]
-    ordering_fields = ['id', "create_time", "update_time", ]
-    filter_class = LocationGroupFilter
-
-    def get_project(self):
-        try:
-            id = self.kwargs.get('pk')
-            return id
-        except:
-            return None
-
-                           
-    def get_queryset(self):             
-        id = self.get_project()
-        if self.request.user:
-            if id is None:
-                return LocationGroupModel.objects.filter()  
+                location_code = location_list[location_min_index].location_code
+                self.update_location_status(location_code,'occupied')
+                return location_list[location_min_index]
+        elif status == 2:
+            print(f"部分入库")
+            # 2. 获取库位组
+            location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
+            print(f"库位列表:{location_list}")
+            location_min_index = 1
+            print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
+            if not location_list[location_min_index]:
+                # 库位已满,返回None
+                return None
             else:
-                return LocationGroupModel.objects.filter(id=id)            
-        else:
-            return LocationGroupModel.objects.none()                           
-    def get_serializer_class(self):                                             
-        if self.action == 'list':
-            return LocationGroupListSerializer          
-
-        elif self.action == 'update':
-            return LocationGroupPostSerializer
-
-        elif self.action =='retrieve':
-            return LocationGroupListSerializer      
-    
-    def update(self, request, *args, **kwargs):
-        data = self.request.data
-        order_month = str(timezone.now().strftime('%Y%m'))
-        data['month'] = order_month
-        group_code = data.get('group_code')
-        # 处理库位组对象
-        group_obj = LocationGroupModel.objects.filter(group_code=group_code).first()
-        if group_obj:
-            data['id'] = group_obj.id
-            logger.info(f"库位组 {group_code} 已存在")
-        else:
-            logger.info(f"库位组 {group_code} 不存在,创建库位组对象")
-            serializer_list = LocationGroupPostSerializer(data=data)
-            serializer_list.is_valid(raise_exception=True)
-            serializer_list.save()
-            data['id'] = serializer_list.data.get('id')
-        return Response(data, status=status.HTTP_201_CREATED)
+                location_code = location_list[location_min_index].location_code
+                self.update_location_status(location_code,'occupied')
+                return location_list[location_min_index]
+  

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


+ 18 - 0
bound/migrations/0003_boundbatchmodel_container_number.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-04-17 20:11
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0002_alter_boundbatchmodel_status'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='boundbatchmodel',
+            name='container_number',
+            field=models.IntegerField(default=0, verbose_name='托盘数目'),
+        ),
+    ]

BIN
bound/migrations/__pycache__/0003_boundbatchmodel_container_number.cpython-38.pyc


+ 1 - 1
bound/models.py

@@ -53,7 +53,7 @@ class BoundBatchModel(models.Model):
     goods_out_qty = models.BigIntegerField(default=0, verbose_name="出库数量")
 
     status = models.IntegerField(choices=CONTAINER_STATUS, default=0, verbose_name='批次状态')
-
+    container_number = models.IntegerField( default=0, verbose_name="托盘数目")
     goods_weight = models.FloatField(default=0, verbose_name="商品单重")
     goods_total_weight = models.FloatField(default=0, verbose_name="商品总重")
 

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


+ 0 - 92
data_base/generate_location group copy.py

@@ -1,92 +0,0 @@
-# generate_locations.py
-import os
-import django
-import sys
-
-# fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
-# fun:get_location_type: 根据托盘数目获取库位类型
-# fun:updata_location_container_link: 更新库位和托盘的关联关系
-# fun:get_batch_status: 获取批次状态
-# fun:get_batch: 获取批次
-# fun:get_location_list_remainder: 获取可用库位的c_number列表
-# fun:get_min_list_index: 获取最小的库位
-# fun:get_location_by_type_remainder: 根据库位类型获取库位
-# fun:get_location_by_type: 第一次入库,根据库位类型获取库位
-# fun:get_location_by_status: 根据库位状态获取库位
-def setup_django():
-    # 使用原始字符串处理Windows路径
-    project_path = "D:/Document/code/vue/greater_wms"
-    sys.path.append(project_path)
-    
-    # 根据实际目录名设置(注意下划线)
-    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'greaterwms.settings')
-    django.setup()
-
-def main():
-    try:
-        # 从正确的应用导入模型
-        from bin.views import LocationAllocation
-        
-        container_code = "12345"
-        print(f"开始生成库位,托盘编码:{container_code}")
-       
-        
-        # 调用生成方法
-       # 修改调用部分的代码
-        allocator = LocationAllocation()  # 创建实例
-        number=allocator.get_pallet_count_by_batch(container_code)  # 通过实例调用)
-        if number is None:
-            print("❌ 该批次下无托盘,请检查托盘编码")
-            return
-        print(f"该批次下托盘总数:{number}")
-        
-        location_type = allocator.get_location_type(number)  # 获取库位类型
-        if not location_type:
-            print("❌ 库位类型获取失败,请检查托盘数量")
-            return
-        print(f"库位类型:{location_type}")
-        # 调用生成库位方法
-        
-        batch_status = allocator.get_batch_status(container_code)  # 获取批次状态
-        if not batch_status:
-            print("❌ 批次状态获取失败,请检查批次号")
-            return
-        print(f"批次状态:{batch_status}")
-
-        batch = allocator.get_batch(container_code)
-        if not batch:
-            print("❌ 批次获取失败,请检查托盘编码")
-            return
-        print(f"批次信息:{batch}")
-
-        location_list_cnumber = allocator.get_location_by_status(container_code, 'in2', 1)  # 获取库位列表
-        if not location_list_cnumber:
-            print("❌ 通用库位获取失败,请检查托盘编码")
-            return
-        print(f"库位列表:{location_list_cnumber}")
-        updata_location_container_link = allocator.updata_location_container_link(location_list_cnumber.location_code, container_code)  # 更新库位和托盘的关联关系
-        if not updata_location_container_link:
-            print("❌ 库位和托盘的关联关系更新失败,请检查托盘编码")
-            return
-        print(f"库位和托盘的关联关系更新成功!")
-        location_list = allocator.get_location_by_type(location_type, 'in2', 1)  # 获取库位列表
-        if not location_list:
-            print("❌ 第一次库位获取失败,请检查库位类型")
-            return
-        print(f"库位列表:{location_list}")
-        location_list_cnumber = allocator.get_location_by_type_remainder(batch, 1)  # 获取库位列表
-        if not location_list_cnumber:
-            print("❌ 剩余库位获取失败,请检查托盘编码")
-            return
-        print(f"库位列表:{location_list_cnumber}")
-        print("✅ 方法生成成功!")
-
-        
-    except Exception as e:
-        print(f"❌ 生成失败:{str(e)}")
-        import traceback
-        traceback.print_exc()
-
-if __name__ == "__main__":
-    setup_django()
-    main()

+ 98 - 0
data_base/inbound_task copy.py

@@ -0,0 +1,98 @@
+# generate_locations.py
+import os
+import django
+import sys
+
+# fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
+# fun:get_location_type: 根据托盘数目获取库位类型
+# fun:updata_location_container_link: 更新库位和托盘的关联关系
+# fun:get_batch_status: 获取批次状态
+# fun:get_batch: 获取批次
+# fun:get_location_list_remainder: 获取可用库位的c_number列表
+# fun:get_min_list_index: 获取最小的库位
+# fun:get_location_by_type_remainder: 根据库位类型获取库位
+# fun:get_location_by_type: 第一次入库,根据库位类型获取库位
+# fun:get_location_by_status: 根据库位状态获取库位
+def setup_django():
+    # 使用原始字符串处理Windows路径
+    project_path = "D:/Document/code/vue/greater_wms"
+    sys.path.append(project_path)
+    
+    # 根据实际目录名设置(注意下划线)
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'greaterwms.settings')
+    django.setup()
+
+def main():
+    try:
+
+        from bin.views import LocationAllocation
+        container_code = "12345"
+        print(f"开始生成库位,托盘编码:{container_code}")
+        allocator = LocationAllocation()  # 创建实例
+        location_list_cnumber = allocator.get_location_by_status(container_code, 'in2', 1)  # 获取库位列表
+        if not location_list_cnumber:
+            print("❌ 通用库位获取失败,请检查托盘编码")
+            return
+        print(f"[1]库位:{location_list_cnumber}")
+        
+        update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'reserverd')  # 更新库位状态
+        if not update_location_status:
+            print("❌ 库位状态更新失败,请检查托盘编码")
+            return
+        print(f"[2]发送任务,库位状态更新成功!")
+        update_location_group_status = allocator.update_location_group_status(location_list_cnumber.location_code)  # 更新库位组状态
+        if not update_location_group_status:
+            print("❌ 库位组状态更新失败,请检查托盘编码")
+            return
+        print(f"[3]库位组状态更新成功!")
+
+        update_batch_status = allocator.update_batch_status(container_code, '2')  # 更新批次状态
+        if not update_batch_status:
+            print("❌ 批次状态更新失败,请检查批次号")
+            return
+        print(f"[4]批次状态更新成功!")
+
+        update_location_group_batch = allocator.update_location_group_batch(location_list_cnumber, container_code)  # 更新库位组的批次
+        if not update_location_group_batch:
+            print("❌ 库位组批次更新失败,请检查托盘编码")
+            return
+        print(f"[5]库位组批次更新成功!")
+        
+        update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'occupied')  # 更新库位状态
+        if not update_location_status:
+            print("❌ 库位状态更新失败,请检查托盘编码")
+            return
+        print(f"[6]WCS到位,库位状态更新成功!")
+
+        update_location_container_link = allocator.update_location_container_link(location_list_cnumber.location_code, container_code)  # 更新库位和托盘的关联关系
+        if not update_location_container_link:
+            print("❌ 库位和托盘的关联关系更新失败,请检查托盘编码")
+            return
+        print(f"[7]库位和托盘的关联关系更新成功!")
+
+
+
+ 
+
+        
+        # location_list = allocator.get_location_by_type(location_type, 'in2', 1)  # 获取库位列表
+        # if not location_list:
+        #     print("❌ 第一次库位获取失败,请检查库位类型")
+        #     return
+        # print(f"库位列表:{location_list}")
+        # location_list_cnumber = allocator.get_location_by_type_remainder(batch, 1)  # 获取库位列表
+        # if not location_list_cnumber:
+        #     print("❌ 剩余库位获取失败,请检查托盘编码")
+        #     return
+        # print(f"库位列表:{location_list_cnumber}")
+        print("✅ 方法生成成功!")
+
+        
+    except Exception as e:
+        print(f"❌ 生成失败:{str(e)}")
+        import traceback
+        traceback.print_exc()
+
+if __name__ == "__main__":
+    setup_django()
+    main()

+ 98 - 0
data_base/inbound_task.py

@@ -0,0 +1,98 @@
+# generate_locations.py
+import os
+import django
+import sys
+
+# fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
+# fun:get_location_type: 根据托盘数目获取库位类型
+# fun:updata_location_container_link: 更新库位和托盘的关联关系
+# fun:get_batch_status: 获取批次状态
+# fun:get_batch: 获取批次
+# fun:get_location_list_remainder: 获取可用库位的c_number列表
+# fun:get_min_list_index: 获取最小的库位
+# fun:get_location_by_type_remainder: 根据库位类型获取库位
+# fun:get_location_by_type: 第一次入库,根据库位类型获取库位
+# fun:get_location_by_status: 根据库位状态获取库位
+def setup_django():
+    # 使用原始字符串处理Windows路径
+    project_path = "D:/Document/code/vue/greater_wms"
+    sys.path.append(project_path)
+    
+    # 根据实际目录名设置
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'greaterwms.settings')
+    django.setup()
+
+def main():
+    try:
+
+        from bin.views import LocationAllocation
+        container_code = "12347"
+        print(f"开始生成库位,托盘编码:{container_code}")
+        allocator = LocationAllocation()  # 创建实例
+        location_list_cnumber = allocator.get_location_by_status(container_code, 'in1', 1)  # 获取库位列表
+        if not location_list_cnumber:
+            print("❌ 通用库位获取失败,请检查托盘编码")
+            return
+        print(f"[1]库位:{location_list_cnumber}")
+        
+        update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'reserverd')  # 更新库位状态
+        if not update_location_status:
+            print("❌ 库位状态更新失败,请检查托盘编码")
+            return
+        print(f"[2]发送任务,库位状态更新成功!")
+        update_location_group_status = allocator.update_location_group_status(location_list_cnumber.location_code)  # 更新库位组状态
+        if not update_location_group_status:
+            print("❌ 库位组状态更新失败,请检查托盘编码")
+            return
+        print(f"[3]库位组状态更新成功!")
+
+        update_batch_status = allocator.update_batch_status(container_code, '2')  # 更新批次状态
+        if not update_batch_status:
+            print("❌ 批次状态更新失败,请检查批次号")
+            return
+        print(f"[4]批次状态更新成功!")
+
+        update_location_group_batch = allocator.update_location_group_batch(location_list_cnumber, container_code)  # 更新库位组的批次
+        if not update_location_group_batch:
+            print("❌ 库位组批次更新失败,请检查托盘编码")
+            return
+        print(f"[5]库位组批次更新成功!")
+        
+        update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'occupied')  # 更新库位状态
+        if not update_location_status:
+            print("❌ 库位状态更新失败,请检查托盘编码")
+            return
+        print(f"[6]WCS到位,库位状态更新成功!")
+
+        update_location_container_link = allocator.update_location_container_link(location_list_cnumber.location_code, container_code)  # 更新库位和托盘的关联关系
+        if not update_location_container_link:
+            print("❌ 库位和托盘的关联关系更新失败,请检查托盘编码")
+            return
+        print(f"[7]库位和托盘的关联关系更新成功!")
+
+
+
+ 
+
+        
+        # location_list = allocator.get_location_by_type(location_type, 'in2', 1)  # 获取库位列表
+        # if not location_list:
+        #     print("❌ 第一次库位获取失败,请检查库位类型")
+        #     return
+        # print(f"库位列表:{location_list}")
+        # location_list_cnumber = allocator.get_location_by_type_remainder(batch, 1)  # 获取库位列表
+        # if not location_list_cnumber:
+        #     print("❌ 剩余库位获取失败,请检查托盘编码")
+        #     return
+        # print(f"库位列表:{location_list_cnumber}")
+        print("✅ 方法生成成功!")
+
+        
+    except Exception as e:
+        print(f"❌ 生成失败:{str(e)}")
+        import traceback
+        traceback.print_exc()
+
+if __name__ == "__main__":
+    setup_django()
+    main()

+ 135 - 0
data_base/test_allocation.py

@@ -0,0 +1,135 @@
+# generate_locations.py
+import os
+import django
+import sys
+
+# fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
+# fun:get_location_type: 根据托盘数目获取库位类型
+# fun:updata_location_container_link: 更新库位和托盘的关联关系
+# fun:get_batch_status: 获取批次状态
+# fun:get_batch: 获取批次
+# fun:get_location_list_remainder: 获取可用库位的c_number列表
+# fun:get_min_list_index: 获取最小的库位
+# fun:get_location_by_type_remainder: 根据库位类型获取库位
+# fun:get_location_by_type: 第一次入库,根据库位类型获取库位
+# fun:get_location_by_status: 根据库位状态获取库位
+def setup_django():
+    # 使用原始字符串处理Windows路径
+    project_path = "D:/Document/code/vue/greater_wms"
+    sys.path.append(project_path)
+    
+    # 根据实际目录名设置(注意下划线)
+    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'greaterwms.settings')
+    django.setup()
+
+def main():
+    try:
+        # 从正确的应用导入模型
+        from bin.views import LocationAllocation
+        
+        container_code = "12345"
+        print(f"开始生成库位,托盘编码:{container_code}")
+       
+        
+        # 调用生成方法
+        # 修改调用部分的代码
+        allocator = LocationAllocation()  # 创建实例
+        number=allocator.get_pallet_count_by_batch(container_code)  # 通过实例调用)
+        if number is None:
+            print("❌ 该批次下无托盘,请检查托盘编码")
+            return
+        print(f"该批次下托盘总数:{number}")
+
+        # 
+        left_number = allocator.get_left_locationGroup_number_by_type()  # 获取每层库位组剩余数量
+        if not left_number:
+            print("❌ 库位组剩余数量获取失败,请检查库位类型")
+            return
+        print(f"库位组剩余数量:{left_number}")
+        
+        # location_type = allocator.get_location_type(number)  # 获取库位类型
+        # if not location_type:
+        #     print("❌ 库位类型获取失败,请检查托盘数量")
+        #     return
+        # print(f"库位类型:{location_type}")
+        # # 调用生成库位方法
+        
+        # batch_status = allocator.get_batch_status(container_code)  # 获取批次状态
+        # if not batch_status:
+        #     print("❌ 批次状态获取失败,请检查批次号")
+        #     return
+        # print(f"批次状态:{batch_status}")
+
+        # batch = allocator.get_batch(container_code)
+        # if not batch:
+        #     print("❌ 批次获取失败,请检查托盘编码")
+        #     return
+        # print(f"批次信息:{batch}")
+
+        # location_list_cnumber = allocator.get_location_by_status(container_code, 'in2', 1)  # 获取库位列表
+        # if not location_list_cnumber:
+        #     print("❌ 通用库位获取失败,请检查托盘编码")
+        #     return
+        # print(f"[1]库位:{location_list_cnumber}")
+        
+        # update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'reserverd')  # 更新库位状态
+        # if not update_location_status:
+        #     print("❌ 库位状态更新失败,请检查托盘编码")
+        #     return
+        # print(f"[2]发送任务,库位状态更新成功!")
+        # update_location_group_status = allocator.update_location_group_status(location_list_cnumber.location_code)  # 更新库位组状态
+        # if not update_location_group_status:
+        #     print("❌ 库位组状态更新失败,请检查托盘编码")
+        #     return
+        # print(f"[3]库位组状态更新成功!")
+
+        # update_batch_status = allocator.update_batch_status(container_code, '2')  # 更新批次状态
+        # if not update_batch_status:
+        #     print("❌ 批次状态更新失败,请检查批次号")
+        #     return
+        # print(f"[4]批次状态更新成功!")
+
+        # update_location_group_batch = allocator.update_location_group_batch(location_list_cnumber, container_code)  # 更新库位组的批次
+        # if not update_location_group_batch:
+        #     print("❌ 库位组批次更新失败,请检查托盘编码")
+        #     return
+        # print(f"[5]库位组批次更新成功!")
+        
+        # update_location_status = allocator.update_location_status(location_list_cnumber.location_code, 'occupied')  # 更新库位状态
+        # if not update_location_status:
+        #     print("❌ 库位状态更新失败,请检查托盘编码")
+        #     return
+        # print(f"[6]WCS到位,库位状态更新成功!")
+
+        # update_location_container_link = allocator.update_location_container_link(location_list_cnumber.location_code, container_code)  # 更新库位和托盘的关联关系
+        # if not update_location_container_link:
+        #     print("❌ 库位和托盘的关联关系更新失败,请检查托盘编码")
+        #     return
+        # print(f"[7]库位和托盘的关联关系更新成功!")
+
+
+
+ 
+
+        
+        # location_list = allocator.get_location_by_type(location_type, 'in2', 1)  # 获取库位列表
+        # if not location_list:
+        #     print("❌ 第一次库位获取失败,请检查库位类型")
+        #     return
+        # print(f"库位列表:{location_list}")
+        # location_list_cnumber = allocator.get_location_by_type_remainder(batch, 1)  # 获取库位列表
+        # if not location_list_cnumber:
+        #     print("❌ 剩余库位获取失败,请检查托盘编码")
+        #     return
+        # print(f"库位列表:{location_list_cnumber}")
+        print("✅ 方法生成成功!")
+
+        
+    except Exception as e:
+        print(f"❌ 生成失败:{str(e)}")
+        import traceback
+        traceback.print_exc()
+
+if __name__ == "__main__":
+    setup_django()
+    main()

BIN
db.sqlite3


+ 15 - 0
logs/server.log

@@ -2670,3 +2670,18 @@ Traceback (most recent call last):
   File "D:\Document\code\vue\greater_wms\.\bin\views.py", line 325, in update
     handle_group_location_status(location_code,location_obj.location_group)
 NameError: name 'handle_group_location_status' is not defined
+[2025-04-17 15:49:38,866][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:49:55,100][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:50:45,077][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:51:18,761][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:53:03,726][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:54:05,763][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:54:34,519][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 15:55:32,365][django.request.log_response():241] [WARNING] Bad Request: /bin/1249/
+[2025-04-17 20:12:22,948][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-17 22:46:16,288][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-17 22:47:30,388][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-17 22:49:52,819][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-17 22:52:05,658][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-17 22:55:58,827][django.request.log_response():241] [WARNING] Not Found: /stock/list/
+[2025-04-17 22:56:10,122][django.request.log_response():241] [WARNING] Not Found: /cyclecount/manualcyclecount/