Browse Source

库位分配init

flower_mr 3 months ago
parent
commit
c857e9870f

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


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


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


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


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


+ 16 - 3
bin/filter.py

@@ -1,5 +1,5 @@
 from django_filters import FilterSet
-from .models import DeviceModel,LocationModel,LocationContainerLink,LocationChangeLog
+from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog
 
 class DeviceFilter(FilterSet):
     class Meta:
@@ -15,7 +15,20 @@ class DeviceFilter(FilterSet):
             "create_time": ['exact', 'range'],
             "update_time": ['exact', 'range'],
         }
-
+class LocationGroupFilter(FilterSet):
+    class Meta:
+        model = LocationGroupModel
+        fields = {
+            "warehouse_code": ['icontains'],
+            "group_name": ['icontains'],
+            "group_type": ['icontains'],
+            "group_code": ['icontains'],
+            "status": ['icontains','exact'],
+       
+            "max_capacity": ['exact', 'range'],
+            "current_quantity": ['exact', 'range'],
+            "location_items": ['exact'],
+        }
 class LocationFilter(FilterSet):
     class Meta:
         model = LocationModel
@@ -30,7 +43,7 @@ class LocationFilter(FilterSet):
             "empty_label": ['exact'],
             "location_code": ['icontains'],
             "location_type": ['icontains'],
-            "status": ['icontains'],
+            "status": ['icontains','exact'],
             "max_capacity": ['exact', 'range'],
             "current_quantity": ['exact', 'range'],
             "coordinate": ['icontains'],

+ 46 - 0
bin/migrations/0007_locationmodel_location_group_and_more.py

@@ -0,0 +1,46 @@
+# Generated by Django 4.1.2 on 2025-04-16 14:03
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bin', '0006_locationmodel_c_number'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='locationmodel',
+            name='location_group',
+            field=models.CharField(default=0, max_length=20, verbose_name='库位组'),
+            preserve_default=False,
+        ),
+        migrations.AlterField(
+            model_name='locationmodel',
+            name='location_type',
+            field=models.CharField(choices=[('T5', '5货位'), ('T4', '4货位'), ('S4', '4单货位'), ('T2', '2货位'), ('T1', '散货位'), ('M1', '通道区'), ('E1', '提升机'), ('C1', '输送机'), ('B1', '充电桩')], max_length=3, verbose_name='货位类型'),
+        ),
+        migrations.CreateModel(
+            name='LocationGroupModel',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('warehouse_code', models.CharField(max_length=50, verbose_name='仓库编码')),
+                ('group_name', models.CharField(max_length=50, verbose_name='库位组名称')),
+                ('group_type', models.CharField(choices=[('T5', '5货位'), ('T4', '4货位'), ('S4', '4单货位'), ('T2', '2货位'), ('T1', '散货位')], max_length=50, verbose_name='库位组类型')),
+                ('group_code', models.CharField(max_length=50, verbose_name='库位组编码')),
+                ('status', models.CharField(choices=[('available', '可用'), ('occupied', '占用'), ('disabled', '禁用'), ('reserved', '预留'), ('maintenance', '维护中')], default='available', max_length=20, verbose_name='库位状态')),
+                ('max_capacity', models.PositiveIntegerField(verbose_name='最大容量')),
+                ('current_quantity', models.PositiveIntegerField(default=0, verbose_name='当前托盘数')),
+                ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+                ('location_items', models.ManyToManyField(to='bin.locationmodel', verbose_name='库位')),
+            ],
+            options={
+                'verbose_name': 'Location Group',
+                'verbose_name_plural': 'Location Group',
+                'db_table': 'location_group',
+                'ordering': ['-id'],
+                'unique_together': {('warehouse_code', 'group_code')},
+            },
+        ),
+    ]

+ 17 - 0
bin/migrations/0008_remove_locationgroupmodel_create_time.py

@@ -0,0 +1,17 @@
+# Generated by Django 4.1.2 on 2025-04-16 14:29
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bin', '0007_locationmodel_location_group_and_more'),
+    ]
+
+    operations = [
+        migrations.RemoveField(
+            model_name='locationgroupmodel',
+            name='create_time',
+        ),
+    ]

+ 28 - 0
bin/migrations/0009_locationgroupmodel_current_batch_and_more.py

@@ -0,0 +1,28 @@
+# Generated by Django 4.1.2 on 2025-04-16 15:04
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bin', '0008_remove_locationgroupmodel_create_time'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='locationgroupmodel',
+            name='current_batch',
+            field=models.CharField(default='', max_length=50, verbose_name='当前批次'),
+        ),
+        migrations.AddField(
+            model_name='locationgroupmodel',
+            name='current_goods_code',
+            field=models.CharField(default='', max_length=50, verbose_name='当前货物编码'),
+        ),
+        migrations.AddField(
+            model_name='locationgroupmodel',
+            name='current_goods_quantity',
+            field=models.PositiveIntegerField(default=0, verbose_name='当前货物数'),
+        ),
+    ]

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


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


BIN
bin/migrations/__pycache__/0009_locationgroupmodel_current_batch_and_more.cpython-38.pyc


+ 605 - 9
bin/models.py

@@ -14,6 +14,7 @@ class LocationModel(models.Model):
         ('M1', '通道区'),  # 通道区
         ('E1', '提升机'),  # 提升机
         ('C1', '输送机'),  # 输送机
+        ('B1', '充电桩'),  # 货架区
     )
     LOCATION_STATUS = (
         ('available', '可用'),
@@ -33,7 +34,8 @@ class LocationModel(models.Model):
     update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
     empty_label = models.BooleanField(default=True, verbose_name="Empty Flag")
 
-    location_code = models.CharField(max_length=20, unique=True, verbose_name='库位编码') 
+    location_code = models.CharField(max_length=20, unique=True, verbose_name='库位编码')
+    location_group = models.CharField(max_length=20, verbose_name='库位组')
     # 示例:T1-L1C001-1
     # T1-L1C001-1 代表货位类型为T1,层号为1,列号为001,货位号为1
     location_type = models.CharField(max_length=3, choices=LOCATION_TYPES, verbose_name='货位类型')
@@ -77,12 +79,132 @@ class LocationModel(models.Model):
         cls.objects.filter(warehouse_code=warehouse_code).delete()
         """根据规划图生成库位"""
         # 定义核心参数(根据规划图调整)
-        MAIN_AISLES = [18, 29]      # 子通道列号
+        MAIN_AISLES = [18, 1]      # 子通道列号
         SUB_AISLES = [2,8, 13]           # 主通道行号
-    
-        
+        for row in range(1, 14):       # 1-13行
+            for col in range(1, 3):   # 1-19列
+                for layer in range(1, 4): # 1-3层
+                    # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==1 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        if row <2:
+                            loc_type = 'T1' 
+                            c_number = 1
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'T2'
+                            c_number = 16-row
+                            # 生成唯一编码
+                    location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+                    # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
+                    
+                    # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
         for row in range(1, 16):       # 1-15行
-            for col in range(1, 19):   # 1-19列
+            for col in range(3, 17):   # 1-16列
+                for layer in range(1, 4): # 1-3层
+                    # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==18 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        if row <2:
+                            loc_type = 'T1' 
+                            c_number = 1
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'T2'
+                            c_number = 16-row
+
+                    # 生成唯一编码
+                    location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+
+                    # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
+                    
+                    # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
+
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
+        # print("✅ 库位生成成功!") 
+        for row in range(1, 14):       # 1-15行
+            for col in range(17, 20):   # 1-16列
                 for layer in range(1, 4): # 1-3层
                     # 判断通道区
                     if col in MAIN_AISLES or row in SUB_AISLES:
@@ -112,6 +234,7 @@ class LocationModel(models.Model):
 
                     # 生成唯一编码
                     location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
                     # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
                     
                     # 创建库位
@@ -124,6 +247,8 @@ class LocationModel(models.Model):
                         shelf_type=loc_type,
                         defaults={
                             'location_code': location_code,
+                            'location_group': location_group,
+
                             'location_type': loc_type,
                             'max_capacity': {
                                 'T5': 5,
@@ -139,9 +264,9 @@ class LocationModel(models.Model):
                         },
                         access_priority=c_number 
                     )
-        # print("✅ 库位生成成功!")           
+        # print("✅ 库位生成成功!")          
         for row in range(1, 18):       # 1-17行
-            for col in range(19, 30):   # 19-29列
+            for col in range(20, 30):   # 19-29列
                 for layer in range(1, 4): # 1-3层
                      # 判断通道区
                     if col in MAIN_AISLES or row in SUB_AISLES:
@@ -187,14 +312,57 @@ class LocationModel(models.Model):
                             loc_type = 'S4'
                             c_number = 18-row
 
+                   
+                    
                     # 生成唯一编码
                     location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+                    # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
                     
-                    # 生成唯一编码
+                    # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
+
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'S4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0,
+                                'B1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
+
+        # 输送机
+        for row in [14]:       # 1-17行
+            for col in [1,18]:   # 1-19列
+                for layer in range(1, 4): # 1-3层
+                    # 判断货位类型(根据实际规划)
+                    loc_type = 'C1'
+                    c_number = 1
                     location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+
                     # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
                     
                     # 创建库位
+                     # 创建库位
                     cls.objects.update_or_create(
                         warehouse_code=warehouse_code,
                         row=row,
@@ -204,6 +372,8 @@ class LocationModel(models.Model):
                         shelf_type=loc_type,
                         defaults={
                             'location_code': location_code,
+                            'location_group': location_group,
+
                             'location_type': loc_type,
                             'max_capacity': {
                                 'T5': 5,
@@ -213,14 +383,440 @@ class LocationModel(models.Model):
                                 'T1': 1,
                                 'M1': 0,
                                 'E1': 0,
-                                'C1': 0
+                                'C1': 0,
+                                'B1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
+        for row in [16]:       # 1-17行
+            for col in [1,18]:   # 1-19列
+                for layer in [1]: # 1-3层
+                    # 判断货位类型(根据实际规划)
+                    loc_type = 'C1'
+                    c_number = row
+                    location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+
+                     # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
+
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'S4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0,
+                                'B1': 0
                             }[loc_type],
                             'coordinate': f"{row}-{col}-{layer}",
                             'is_active': True
                         },
                         access_priority=c_number 
                     )
+        # 提升机
+        for row in [15]:       # 1-17行
+            for col in [1,18]:   # 1-19列
+                for layer in range(1, 4): # 1-3层
+                    # 判断货位类型(根据实际规划)
+                    loc_type = 'E1'
+                    c_number = row
+                    location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+                     # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
 
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'S4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0,
+                                'B1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
+        # 充电桩
+        for row in [14]:       # 1-17行
+            for col in [2]:   # 1-19列
+                for layer in range(1, 3): # 1-3层
+                    # 判断货位类型(根据实际规划)
+                    loc_type = 'B1'
+                    c_number = 1
+                    location_code = f"{loc_type}-L{layer}C{col:03d}-{c_number:02d}"
+                    location_group = f"{loc_type}-L{layer}C{col:03d}"
+
+                     # 创建库位
+                    cls.objects.update_or_create(
+                        warehouse_code=warehouse_code,
+                        row=row,
+                        col=col,
+                        layer=layer,
+                        c_number=c_number,
+                        shelf_type=loc_type,
+                        defaults={
+                            'location_code': location_code,
+                            'location_group': location_group,
+
+                            'location_type': loc_type,
+                            'max_capacity': {
+                                'T5': 5,
+                                'T4': 4,
+                                'S4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0,
+                                'B1': 0
+                            }[loc_type],
+                            'coordinate': f"{row}-{col}-{layer}",
+                            'is_active': True
+                        },
+                        access_priority=c_number 
+                    )
+    
+
+class LocationGroupModel(models.Model):
+    LOCATION_TYPES = (
+        ('T5', '5货位'),  # 5托盘/批次
+        ('T4', '4货位'),  # 4托盘/批次
+        ('S4', '4单货位'),  # 4单托盘
+        ('T2', '2货位'),  # 2托盘/批次 
+        ('T1', '散货位'),  # 1托盘
+    )
+    LOCATION_STATUS = (
+        ('available', '可用'),
+        ('occupied', '占用'),
+        ('disabled', '禁用'),
+        ('reserved', '预留'),
+        ('maintenance', '维护中'),
+    )
+    warehouse_code = models.CharField(max_length=50, verbose_name='仓库编码')
+    group_name = models.CharField(max_length=50, verbose_name='库位组名称')
+    group_type = models.CharField(max_length=50, choices=LOCATION_TYPES, verbose_name='库位组类型')
+    group_code = models.CharField(max_length=50, verbose_name='库位组编码')
+    location_items = models.ManyToManyField(LocationModel, 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_goods_quantity = models.PositiveIntegerField(default=0, verbose_name='当前货物数')
+    current_batch = models.CharField(max_length=50, default='', verbose_name='当前批次')
+    current_goods_code = models.CharField(max_length=50, default='', verbose_name='当前货物编码')
+    # create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
+    class Meta:
+        db_table = 'location_group'
+        verbose_name = 'Location Group'
+        verbose_name_plural = "Location Group"
+        ordering = ['-id']
+        unique_together = ( 'warehouse_code', 'group_code')  # 防止重复组编码
+    @classmethod
+    def generate_group(cls,warehouse_code):
+        cls.objects.filter(warehouse_code=warehouse_code).delete()
+        MAIN_AISLES = [18, 1]      # 子通道列号
+        SUB_AISLES = [2,8, 13]           # 主通道行号
+        for row in range(1, 14):       # 1-13行
+            for col in range(1, 3):   # 1-19列
+                for layer in range(1, 4): # 1-3层
+                    # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==1 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        if row <2:
+                            loc_type = 'T1' 
+                            c_number = 1
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'T2'
+                            c_number = 16-row
+                            # 生成唯一编码
+                    print(f"生成库组:{row}-{col}-{layer}")
+                    if loc_type == 'M1':
+                        continue
+                    # 创建库位
+                    group_code = f"{loc_type}-L{layer}C{col:03d}"
+                    group_name = f"{loc_type}-L{layer}C{col:03d}"
+        
+                    if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
+                        group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+                    else:
+                        group_item = cls.objects.create(
+                            warehouse_code=warehouse_code,
+                            group_name=group_name,
+                            group_type=loc_type,
+                            group_code=group_code,
+                            max_capacity={
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'S4': 4,
+
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            current_quantity=0,
+                            status='available'
+                        )
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+        
+        for row in range(1, 16):       # 1-15行
+            for col in range(3, 17):   # 1-16列
+                for layer in range(1, 4): # 1-3层
+                    # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==18 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        if row <2:
+                            loc_type = 'T1' 
+                            c_number = 1
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'T2'
+                            c_number = 16-row
+                         # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
+                    if loc_type == 'M1':
+                        continue
+                    # 创建库位
+                    group_code = f"{loc_type}-L{layer}C{col:03d}"
+                    group_name = f"{loc_type}-L{layer}C{col:03d}"
+        
+                    if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
+                        group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+                    else:
+                        group_item = cls.objects.create(
+                            warehouse_code=warehouse_code,
+                            group_name=group_name,
+                            group_type=loc_type,
+                            group_code=group_code,
+                            max_capacity={
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'S4': 4,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            current_quantity=0,
+                            status='available'
+                        )
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+        
+                   
+        for row in range(1, 14):       # 1-15行
+            for col in range(17, 20):   # 1-16列
+                for layer in range(1, 4): # 1-3层
+                    # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==18 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        if row <2:
+                            loc_type = 'T1' 
+                            c_number = 1
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'T2'
+                            c_number = 16-row
+
+                         # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
+                    if loc_type == 'M1':
+                        continue
+                    # 创建库位
+                    group_code = f"{loc_type}-L{layer}C{col:03d}"
+                    group_name = f"{loc_type}-L{layer}C{col:03d}"
+        
+                    if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
+                        group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+                    else:
+                        group_item = cls.objects.create(
+                            warehouse_code=warehouse_code,
+                            group_name=group_name,
+                            group_type=loc_type,
+                            group_code=group_code,
+                            max_capacity={
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'S4': 4,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            current_quantity=0,
+                            status='available'
+                        )
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+        
+        for row in range(1, 18):       # 1-17行
+            for col in range(20, 30):   # 19-29列
+                for layer in range(1, 4): # 1-3层
+                     # 判断通道区
+                    if col in MAIN_AISLES or row in SUB_AISLES:
+                        loc_type = 'M1'
+                        c_number = row
+                        # 通道
+                    
+                        if col ==18 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+                        if col ==29 and row == 1:
+                            loc_type = 'T1'
+                            c_number = 1
+                        if col ==29 and row == 14:
+                            loc_type = 'S4'
+                            c_number = 4
+                        if col ==29 and row == 15:
+                            loc_type = 'S4'
+                            c_number = 3
+                        if col ==29 and row == 16:
+                            loc_type = 'S4'
+                            c_number = 2
+                        if col ==29 and row == 17:
+                            loc_type = 'S4'
+                            c_number = 1
+                 
+               
+                    # 判断货位类型(根据实际规划)
+                    
+                    else:
+                        # 判断货位类型(根据实际规划)
+                        if row < 2:
+                            loc_type = 'T1' 
+                            c_number = row
+                    
+                        elif row < 8:
+                            loc_type = 'T5'
+                            c_number = row-2
+                        elif row < 13:
+                            loc_type = 'T4'
+                            c_number = row-8
+                        else:
+                            loc_type = 'S4'
+                            c_number = 18-row
+
+                    # print(f"生成库位:{location_code}-{row}-{col}-{layer}")
+                    if loc_type == 'M1':
+                        continue
+                    # 创建库位
+                    group_code = f"{loc_type}-L{layer}C{col:03d}"
+                    group_name = f"{loc_type}-L{layer}C{col:03d}"
+        
+                    if cls.objects.filter(warehouse_code=warehouse_code, group_code=group_code).exists():
+                        group_item = cls.objects.get(warehouse_code=warehouse_code, group_code=group_code)
+                        group_item.location_items.add(LocationModel.objects.get(warehouse_code=warehouse_code, row=row, col=col, layer=layer))
+                        group_item.save()
+                    else:
+                        group_item = cls.objects.create(
+                            warehouse_code=warehouse_code,
+                            group_name=group_name,
+                            group_type=loc_type,
+                            group_code=group_code,
+                            max_capacity={
+                                'T5': 5,
+                                'T4': 4,
+                                'T2': 2,
+                                'T1': 1,
+                                'S4': 4,
+                                'M1': 0,
+                                'E1': 0,
+                                'C1': 0
+                            }[loc_type],
+                            current_quantity=0,
+                            status='available'
+                        )
+                        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):

+ 17 - 1
bin/serializers.py

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 
-from .models import DeviceModel,LocationModel,LocationContainerLink,LocationChangeLog
+from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog
 
 
 class LocationSerializer(serializers.ModelSerializer):
@@ -19,6 +19,22 @@ class LocationPostSerializer(serializers.ModelSerializer):
         fields = '__all__'
         read_only_fields = ['id']
 
+class LocationGroupSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = LocationGroupModel
+        fields = '__all__'
+        read_only_fields = ['id']
+class LocationGroupListSerializer(serializers.ModelSerializer ):
+    class Meta:
+        model = LocationGroupModel
+        fields = '__all__'
+        read_only_fields = ['id ']
+class LocationGroupPostSerializer(serializers.ModelSerializer):
+    class Meta:
+        model = LocationGroupModel
+        fields = '__all__'
+        read_only_fields = ['id']
+
 
 
 

+ 3 - 1
bin/urls.py

@@ -3,8 +3,10 @@ from . import views
 
 urlpatterns = [
     path ('', views.locationViewSet.as_view({"get": "list"}), name='location_list'),
-   re_path(r'^(?P<pk>\d+)/$',  views.locationViewSet.as_view({"get": "retrieve", "put": "update"}), name='location_detail'),
+    re_path(r'^(?P<pk>\d+)/$',  views.locationViewSet.as_view({"get": "retrieve", "put": "update"}), name='location_detail'),
 
+    path (r'group/', views.locationGroupViewSet.as_view({"get": "list"}), name='location_list'),
+    re_path(r'^group/(?P<pk>\d+)/$',  views.locationGroupViewSet.as_view({"get": "retrieve", "put": "update"}), name='location_detail'),
     # path(r'management/', views.stockshelfViewSet.as_view({"get": "list", "post": "create"}), name="management"),
     # re_path(r'^management/(?P<pk>\d+)/$', views.stockshelfViewSet.as_view({'get': 'retrieve','put': 'update','patch': 'partial_update','delete': 'destroy'}), name="staff_1"),
 

+ 112 - 6
bin/views.py

@@ -11,17 +11,62 @@ from django.utils import timezone
 from django.db import transaction
 import logging
 from rest_framework import status
-from .models import DeviceModel,LocationModel,LocationContainerLink,LocationChangeLog
+from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog,ContainerDetailModel
 from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
 
 
-from .filter import DeviceFilter,LocationFilter,LocationContainerLinkFilter,LocationChangeLogFilter
+from .filter import DeviceFilter,LocationFilter,LocationContainerLinkFilter,LocationChangeLogFilter,LocationGroupFilter
 from .serializers import LocationListSerializer,LocationPostSerializer
+from .serializers import LocationGroupListSerializer,LocationGroupPostSerializer
 # 以后添加模块时,只需要在这里添加即可
 from rest_framework.permissions import AllowAny
-
+from container.models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel,
 logger = logging.getLogger(__name__)
 
+# 库位分配
+class LocationAllocation:
+    @transaction.atomic
+    def get_pallet_count_by_batch(self, container_code):
+        """
+        根据托盘码查询批次下托盘总数
+        :param container_code: 要查询的托盘码
+        :return: 所属批次下的托盘总数
+        """
+        # 1. 通过托盘码获取容器详情
+        container_detail = ContainerDetailModel.objects.filter(
+            container_code=container_code
+        ).select_related('bound_detail').first()
+
+        if not container_detail:
+            logger.error(f"托盘 {pallet_code} 不存在")
+  
+        # 2. 获取关联的批次明细
+        bound_detail = container_detail.bound_detail
+        if not bound_detail:
+            logger.error(f"容器 {container_detail.container_code} 不存在")
+
+        # 3. 获取父级批次
+        batch = BoundBatchModel.objects.filter(
+            batch_code=bound_detail.batch_code
+        ).prefetch_related('bound_details').first()
+
+        if not batch:
+            logger.error(f"批次 {bound_detail.batch_code} 不存在")
+
+        # 4. 统计批次下所有托盘数量(两种方式)
+        # 方式一:直接统计关联明细数量(如果每个detail对应一个托盘)
+        total_pallets = batch.bound_details.count()
+        
+        # 方式二:累加明细中的容器数量(如果detail包含多个容器)
+        # total_pallets = sum(detail.container_count for detail in batch.bound_details.all())
+
+        return {
+            "batch_code": batch.batch_code,
+            "total_pallets": total_pallets,
+            "current_pallet": pallet_code
+        }
+
+
 class locationViewSet(viewsets.ModelViewSet):
     """
         retrieve:
@@ -67,9 +112,6 @@ class locationViewSet(viewsets.ModelViewSet):
         elif self.action =='retrieve':
             return LocationListSerializer
 
-
-
-
     def update(self, request, *args, **kwargs):
         data = self.request.data
         order_month = str(timezone.now().strftime('%Y%m'))
@@ -88,4 +130,68 @@ class locationViewSet(viewsets.ModelViewSet):
             data['id'] = serializer_list.data.get('id')
         return Response(data, status=status.HTTP_201_CREATED)
 
+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)

+ 2 - 1
container/views.py

@@ -195,7 +195,8 @@ class ContainerWCSViewSet(viewsets.ModelViewSet):
             )
             serializer.is_valid(raise_exception=True)
             serializer.save()
-
+            # 库位分配
+             
             # 检查是否已在目标位置
             if current_location == str(container_obj.target_location):
                 logger.info(f"托盘 {container} 已在目标位置")

+ 36 - 0
data_base/generate_location group.py

@@ -0,0 +1,36 @@
+# generate_locations.py
+import os
+import django
+import sys
+
+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.models import LocationGroupModel
+        
+        warehouse_code = "W01"
+        print(f"开始生成库位,仓库编码:{warehouse_code}")
+        
+        # 调用生成方法
+        LocationGroupModel.generate_group(warehouse_code)
+        
+        print("✅ 库位生成成功!")
+        print(f"共生成库位数:{LocationGroupModel.objects.count()}条")
+        
+    except Exception as e:
+        print(f"❌ 生成失败:{str(e)}")
+        import traceback
+        traceback.print_exc()
+
+if __name__ == "__main__":
+    setup_django()
+    main()

+ 1 - 1
data_base/generate_location.py

@@ -17,7 +17,7 @@ def main():
         # 从正确的应用导入模型
         from bin.models import LocationModel
         
-        warehouse_code = "WH001"
+        warehouse_code = "W01"
         print(f"开始生成库位,仓库编码:{warehouse_code}")
         
         # 调用生成方法

BIN
db.sqlite3


+ 98 - 0
logs/error.log

@@ -2295,3 +2295,101 @@ Traceback (most recent call last):
   File "d:\language\python38\lib\site-packages\rest_framework\generics.py", line 122, in get_serializer_class
     assert self.serializer_class is not None, (
 AssertionError: 'locationViewSet' should either include a `serializer_class` attribute, or override the `get_serializer_class()` method.
+[2025-04-16 14:51:39,184][django.request.log_response():241] [ERROR] Internal Server Error: /bin/group/
+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:\language\python38\lib\site-packages\rest_framework\mixins.py", line 43, in list
+    return self.get_paginated_response(serializer.data)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 768, in data
+    ret = super().data
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 253, in data
+    self._data = self.to_representation(self.instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 686, in to_representation
+    return [
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 687, in <listcomp>
+    self.child.to_representation(item) for item in iterable
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 507, in to_representation
+    for field in fields:
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 368, in _readable_fields
+    for field in self.fields.values():
+  File "d:\language\python38\lib\site-packages\django\utils\functional.py", line 57, in __get__
+    res = instance.__dict__[self.name] = self.func(instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 356, in fields
+    for key, value in self.get_fields().items():
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 1032, in get_fields
+    assert hasattr(self.Meta, 'model'), (
+AssertionError: Class LocationGroupListSerializer missing "Meta.model" attribute
+[2025-04-16 14:53:40,310][django.request.log_response():241] [ERROR] Internal Server Error: /bin/group/
+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:\language\python38\lib\site-packages\rest_framework\mixins.py", line 43, in list
+    return self.get_paginated_response(serializer.data)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 768, in data
+    ret = super().data
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 253, in data
+    self._data = self.to_representation(self.instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 686, in to_representation
+    return [
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 687, in <listcomp>
+    self.child.to_representation(item) for item in iterable
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 507, in to_representation
+    for field in fields:
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 368, in _readable_fields
+    for field in self.fields.values():
+  File "d:\language\python38\lib\site-packages\django\utils\functional.py", line 57, in __get__
+    res = instance.__dict__[self.name] = self.func(instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 356, in fields
+    for key, value in self.get_fields().items():
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 1032, in get_fields
+    assert hasattr(self.Meta, 'model'), (
+AssertionError: Class LocationGroupListSerializer missing "Meta.model" attribute

+ 113 - 0
logs/server.log

@@ -2524,3 +2524,116 @@ AssertionError: 'locationViewSet' should either include a `serializer_class` att
 [2025-04-15 22:54:15,305][django.request.log_response():241] [WARNING] Not Found: /bin./
 [2025-04-15 22:58:08,323][django.request.log_response():241] [WARNING] Not Found: /binset/
 [2025-04-15 22:59:59,529][django.request.log_response():241] [WARNING] Not Found: /bin/management/
+[2025-04-16 09:43:04,922][django.request.log_response():241] [WARNING] Not Found: /dn/list/
+[2025-04-16 09:57:10,886][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 11:14:34,086][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 11:15:13,258][django.request.log_response():241] [WARNING] Not Found: /dn/list/
+[2025-04-16 11:29:37,152][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 13:32:40,928][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 14:51:39,184][django.request.log_response():241] [ERROR] Internal Server Error: /bin/group/
+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:\language\python38\lib\site-packages\rest_framework\mixins.py", line 43, in list
+    return self.get_paginated_response(serializer.data)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 768, in data
+    ret = super().data
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 253, in data
+    self._data = self.to_representation(self.instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 686, in to_representation
+    return [
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 687, in <listcomp>
+    self.child.to_representation(item) for item in iterable
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 507, in to_representation
+    for field in fields:
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 368, in _readable_fields
+    for field in self.fields.values():
+  File "d:\language\python38\lib\site-packages\django\utils\functional.py", line 57, in __get__
+    res = instance.__dict__[self.name] = self.func(instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 356, in fields
+    for key, value in self.get_fields().items():
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 1032, in get_fields
+    assert hasattr(self.Meta, 'model'), (
+AssertionError: Class LocationGroupListSerializer missing "Meta.model" attribute
+[2025-04-16 14:53:40,310][django.request.log_response():241] [ERROR] Internal Server Error: /bin/group/
+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:\language\python38\lib\site-packages\rest_framework\mixins.py", line 43, in list
+    return self.get_paginated_response(serializer.data)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 768, in data
+    ret = super().data
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 253, in data
+    self._data = self.to_representation(self.instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 686, in to_representation
+    return [
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 687, in <listcomp>
+    self.child.to_representation(item) for item in iterable
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 507, in to_representation
+    for field in fields:
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 368, in _readable_fields
+    for field in self.fields.values():
+  File "d:\language\python38\lib\site-packages\django\utils\functional.py", line 57, in __get__
+    res = instance.__dict__[self.name] = self.func(instance)
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 356, in fields
+    for key, value in self.get_fields().items():
+  File "d:\language\python38\lib\site-packages\rest_framework\serializers.py", line 1032, in get_fields
+    assert hasattr(self.Meta, 'model'), (
+AssertionError: Class LocationGroupListSerializer missing "Meta.model" attribute
+[2025-04-16 15:56:20,847][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 16:14:40,514][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 16:27:50,981][django.request.log_response():241] [WARNING] Not Found: /bin/flow/
+[2025-04-16 16:27:54,454][django.request.log_response():241] [WARNING] Not Found: /bin/gr/
+[2025-04-16 16:27:55,709][django.request.log_response():241] [WARNING] Not Found: /bin/gro/
+[2025-04-16 16:34:51,704][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/
+[2025-04-16 16:40:03,952][django.request.log_response():241] [WARNING] Not Found: /stock/list/
+[2025-04-16 16:40:06,813][django.request.log_response():241] [WARNING] Not Found: /cyclecount/manualcyclecount/
+[2025-04-16 16:40:27,778][django.request.log_response():241] [WARNING] Not Found: /cyclecount/qtyrecorviewset/

+ 7 - 6
templates/src/components/goodscard.vue

@@ -1,6 +1,6 @@
 <template>
     <div  :style="{ backgroundColor: bgColor }">
-        <div style="color: transparent;"></div>
+        <div style="color: transparent;">1111</div>
         <q-dialog v-model="clickedinput" transition-show="jump-down" transition-hide="jump-up">
             <q-card style="min-width: 350px; ">
                 <q-bar class="bg-light-blue-10 text-white rounded-borders" style="height: 50px">
@@ -276,8 +276,10 @@ export default {
         rowIndex: Number,
         colIndex: Number,
         layerIndex: Number,
+        selectedShelfType: String,
         goodsData: Object,
 
+
     },
     data() {
         return {
@@ -360,11 +362,8 @@ export default {
         }
     },
     created() {
-        this.shelfLocal = this.goodsData.shelf_type;
-       
+        this.shelfLocal = this.selectedShelfType;
         this.handleclick()
-
-
     },
 
     methods: {
@@ -408,8 +407,10 @@ export default {
             console.log("newDataSubmit")
             console.log(this.newFormData)
 
-        },
+        },                                                 
         handleclick() {
+            this.shelfLocal = this.selectedShelfType;
+            
       
             if (this.shelfLocal == "undefined") { this.clickedinput = true, this.storage_dialog = false, this.elevator_dialog = false, this.conveyor_dialog = false }
             if (this.shelfLocal == "storage") { this.getList(), this.clickedinput = false, this.storage_dialog = true, this.elevator_dialog = false, this.conveyor_dialog = false }

+ 1 - 1
templates/src/pages/dashboard/flows_statements.vue

@@ -520,7 +520,7 @@ export default {
       max: 0,
       total: 0,
       paginationIpt: 1,
-      current: 1,
+
 
     }
 

+ 143 - 118
templates/src/pages/stock/management.vue

@@ -24,6 +24,7 @@
                 :col-index="select_Inventory.colIndex"
                 :row-index="select_Inventory.rowIndex"
                 :layer-index="select_Inventory.layerIndex"
+                :selected-shelf-type="select_Inventory.shelf_type"
                 :goods-data="select_Inventory.goods_data"
                 @close="showInventoryDetails = false"
                  
@@ -39,9 +40,9 @@
                         </div>
                     </div>
                     <div class="axis-arrow"></div>
-
+  
                 </div>
-
+  
                 <!-- X轴 -->
                 <div class="axis x-axis">
                     <div class="axis-arrow"></div>
@@ -50,18 +51,18 @@
                             {{ col }}
                         </div>
                         <div class="axis-label">
-
+  
                         </div>
                     </div>
                 </div>
-
+  
                 <!-- 网格系统 -->
                 <div class="grid-container">
                     <!-- 内容层 --> 
                     <div class="grid-content">
-                        <div v-for="(row, rowIndex) in shelf.rows" :key="`row-${rowIndex}|${shelf.layer_now}`" class="grid-row">
-                            <div v-for="(col, colIndex) in shelf.cols" :key="`col-${colIndex}|${shelf.layer_now}`" class="grid-item">
-                                <div 
+                        <div v-for="(row, rowIndex) in shelf.rows" :key="`row-${rowIndex}|${shelf.layer_now}`" class="grid-row" :style="{cursor: 'pointer'}">
+                            <div v-for="(col, colIndex) in shelf.cols" :key="`col-${colIndex}|${shelf.layer_now}`" class="grid-item" :style="{cursor: 'pointer'}">
+                                <div class="select-item"
                                 v-if="shouldShowButton(
                                     shelf.rows - rowIndex, 
                                     colIndex + 1, 
@@ -78,9 +79,14 @@
                                 }"
                                 @click="handleBinClick(shelf.rows - rowIndex, colIndex+1, shelf.layer_now)"
                             >
-                                <!-- 确保没有子元素获得焦点 -->
+                        
                             </div>
-                                <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[20, 20]"
+  
+                                <q-tooltip   v-if="shouldShowButton(
+                                    shelf.rows - rowIndex, 
+                                    colIndex + 1, 
+                                    shelf.layer_now
+                                )" content-class="bg-amber text-black shadow-4" :offset="[20, 20]"
                                     content-style="font-size: 10px">
                                     {{ $t('stock.rowtip') }} {{ shelf.rows - rowIndex }}
                                     {{ $t('stock.coltip') }} {{ colIndex + 1 }}
@@ -105,11 +111,11 @@ export default {
     data() {
         return {
             pathname: 'bin/',
-
+  
             warehouse_code: '',
             warehouse_name: '',
             shelf_name: 'A区货架',
-
+  
             shelf: {
                 rows: 17,           // 控制行数
                 cols: 29,           // 控制列数
@@ -119,11 +125,10 @@ export default {
             filter: "",
             auth_edit: false,
             goodsMap: {},  // 
-
+  
             goodsMatrix: [] ,   // 二维数据矩阵
    
             // 颜色配置
-             // 颜色配置
             binColors: {
             T1: 'rgba(255, 215, 0, 0.5)',  // 黄色半透明
             T2: 'rgba(255, 165, 0, 0.5)',  // 黄色半透明
@@ -131,11 +136,12 @@ export default {
             T5: 'rgba(255, 65, 0, 0.5)',  // 黄色半透明
             S4: 'rgba(255, 115, 0, 0.5)',  // 红色半透明
             M1: 'rgba(255, 255, 0, 0.5)',  // 黄色半透明
-            E1: 'rgba(255, 255, 0, 0.5)',  // 黄色半透明
-            C1: 'rgba(255, 255, 0, 0.5)',  // 黄色半透明
+            E1: 'rgba(128, 98, 11, 0.5)',  // 黄色半透明
+            C1: 'rgba(128, 135, 128, 0.5)',  // 黄色半透明
+            B1: 'rgba(0, 195, 0, 0.5)',  // 绿色半透明
             default: 'rgba(255, 0.5)' // 白色半透明
-            
-             }   ,
+          
+            } ,
             showInventoryDetails : false, // 显示库存详情
             select_Inventory: {
                 rowIndex : 0,
@@ -156,7 +162,7 @@ export default {
         },
         beforeDestroy() {
             //清空数据
-            this.goodsMap = {} 
+            this.goodsMap = {}
             this.goodsMatrix = []
     
         },
@@ -164,8 +170,8 @@ export default {
         shouldShowButton(row, col, layer) {
             const bin = this.goodsMap[`${row}-${col}-${layer}`]
             // 示例:仅显示storage类型的库位
-            return ['T1', 'T2', 'T4', 'T5', 'S4', 'M1', 'E1', 'C1'].includes(bin?.location_type) // 显示多种类型
-            // return ['storage', 'occupied'].includes(bin?.shelf_type) // 显示多种类型
+            // return bin?.shelf_type === 'storage' 
+            return ['T1', 'T2', 'T4', 'T5', 'S4', 'M1', 'E1', 'C1','B1'].includes(bin?.location_type) // 显示多种类型
         },
         getList() {
             var _this = this;
@@ -176,7 +182,11 @@ export default {
                     _this.goodsMap = {};
                     res.results.forEach(item => {
                         const key = `${item.row}-${item.col}-${item.layer}`;
-                        _this.goodsMap[key] = item;
+                        _this.goodsMap[key] = {
+                            id:item.id,
+                            location_type: item.location_type,
+                            shelf_type: item.shelf_type,
+                        };
                     });
                 
                     _this.$q.notify({
@@ -209,31 +219,46 @@ export default {
         if (!bin) return this.binColors.default;
         return this.binColors[bin.shelf_type] || this.binColors.default;
         },
-
+  
         // 货位点击处理
         handleBinClick(row, col, layer) {
             this.select_Inventory.rowIndex = row
             this.select_Inventory.colIndex = col
             this.select_Inventory.layerIndex = layer
+            console.log(this.goodsMap[`${row}-${col}-${layer}`])
+            if (['T1', 'T2', 'T4', 'T5', 'S4'].includes(this.goodsMap[`${row}-${col}-${layer}`]?.location_type))
+                {
+                    this.select_Inventory.shelf_type = "storage"
+                }
+            else if ([ 'E1', 'C1'].includes(this.goodsMap[`${row}-${col}-${layer}`]?.location_type))
+                {
+                    this.select_Inventory.shelf_type = "elevator"
+                }
+            else
+                {
+                    this.select_Inventory.shelf_type = "corridor"
+                }
             this.select_Inventory.goods_data = this.goodsMap[`${row}-${col}-${layer}`]
             this.showInventoryDetails = true
             console.log(this.select_Inventory)
-            this.$refs.goodscard.handleclick()
+            this.$nextTick(() => {
+                this.$refs.goodscard.handleclick();
+            });
           
             
         },
-
+  
         updateCSSVariables() {
             const root = document.documentElement
             // 获取组件容器的实际尺寸
             const dwidth = document.documentElement.clientWidth
             const dheight = document.documentElement.clientHeight
             console.log(dwidth, dheight)
-
+  
             // 
             const width = dwidth * 0.6
             const height = dheight * 0.6
-
+  
             //计算网格的宽度
             var cell_d = width * 7 / 8 / this.shelf.cols //页面占比
             var cell_x = cell_d *  1/ 5 //网格占比
@@ -251,7 +276,7 @@ export default {
             //console.log(axis_x)
             root.style.setProperty('--cell-d', `${cell_d}px`)
             root.style.setProperty('--cell-d-x', `${cell_d + cell_x}px`)
-
+  
             root.style.setProperty('--cell-x-2', `${cellSize}px`)
             root.style.setProperty('--cell-x', `${cell_x}px`)
             root.style.setProperty('--cell-y', `${cellGap + cell_d}px`)
@@ -271,7 +296,7 @@ export default {
                 this.shelf.layer_now -= 1
                 this.reFresh()
             }
-
+  
         },
         handleShelfUp() {
             if (this.shelf.layer_now < this.shelf.layers) {
@@ -285,16 +310,16 @@ export default {
         reFresh() {
             this.handle_setting()
             this.getList()
-
+  
         },
         handle_edit() {
             // 取反
             this.auth_edit = !this.auth_edit
             LocalStorage.set('auth_edit', this.auth_edit)
-
-
+  
+  
         }
-
+  
     },
     mounted() {
         this.updateCSSVariables()
@@ -305,7 +330,7 @@ export default {
         // 清理数据
         this.goodsMap = {}
         this.goodsMatrix = []
-
+  
         
         // 清理事件监听
         window.removeEventListener('resize', this.handleResize)
@@ -317,7 +342,7 @@ export default {
         }
     },
     created() {
-
+  
         LocalStorage.set('auth_edit', this.auth_edit)
         if (LocalStorage.has('warehouse_code')) {
             this.warehouse_code = LocalStorage.getItem('warehouse_code')
@@ -326,14 +351,14 @@ export default {
             this.warehouse_name = LocalStorage.getItem('warehouse_name')
         }
         this.getList()
-
+  
     }
-}
-</script>
-
-<style scoped>
-:root {
-
+  }
+  </script>
+  
+  <style scoped>
+  :root {
+  
     --cell-d: 40px;
     --cell-d-x: 100px;
     --cell-x-2: 20px;
@@ -341,18 +366,18 @@ export default {
     --cell-y: 100px;
     --cell-y-2: 20px;
     --axis-x: 20px;
-}
-
-.btn-group {
+  }
+  
+  .btn-group {
     position: absolute;
     left: var(--cell-x-2);
     display: flex;
     gap: 10px;
-}
-
-
-/* 网格系统容器 */
-.grid-system {
+  }
+  
+  
+  /* 网格系统容器 */
+  .grid-system {
     position: relative;
     padding-left: var(--cell-x-2);
     padding-right: 330px;
@@ -360,61 +385,61 @@ export default {
     padding-top: 10px;
     /* 下边留出X轴空间 */
     min-width: max-content;
-}
-
-/* 坐标轴通用样式 */
-.axis {
-
+  }
+  
+  /* 坐标轴通用样式 */
+  .axis {
+  
     position: absolute;
-
+  
     background: #333;
     z-index: 2;
-}
-
-/* 箭头 */
-.axis-arrow {
+  }
+  
+  /* 箭头 */
+  .axis-arrow {
     position: absolute;
-
+  
     border-top: 6px solid transparent;
     border-bottom: 6px solid transparent;
     border-left: 12px solid #555;
-
-}
-
-.y-axis .axis-arrow {
+  
+  }
+  
+  .y-axis .axis-arrow {
     top: -10px;
     left: -4px;
     border-left: 5px solid transparent;
     border-right: 5px solid transparent;
     border-bottom: 10px solid #333;
-
-}
-
-.x-axis .axis-arrow {
+  
+  }
+  
+  .x-axis .axis-arrow {
     right: -3px;
     top: -5px;
     border-left-color: #333;
-}
-
-/* Y轴样式 */
-.y-axis {
+  }
+  
+  /* Y轴样式 */
+  .y-axis {
     left: 30px;
     top: 0;
     bottom: -10px;
     /* 留出X轴空间 */
     width: 2px;
-}
-
-.y-axis .axis-numbers {
+  }
+  
+  .y-axis .axis-numbers {
     position: absolute;
     right: 6px;
-
+  
     height: 100%;
     display: flex;
     flex-direction: column-reverse;
-}
-
-.y-axis .axis-numbers div {
+  }
+  
+  .y-axis .axis-numbers div {
     position: relative;
     height: var(--cell-y);
     /* 与网格行高一致 */
@@ -423,73 +448,73 @@ export default {
     /* 垂直居中 */
     color: #111;
     font-size: larger;
-}
-
-/* X轴样式 */
-.x-axis {
+  }
+  
+  /* X轴样式 */
+  .x-axis {
     position: absolute;
     left: 30px;
     width: var(--axis-x);
     /* 直接使用变量控制宽度 */
     right: auto;
     bottom: -10px;
-
+  
     height: 2px;
-}
-
-.x-axis .axis-numbers {
+  }
+  
+  .x-axis .axis-numbers {
     position: absolute;
     top: 10px;
     /* 数字显示在轴线下方 */
-
+  
     display: flex;
-}
-
-.x-axis .axis-numbers div {
+  }
+  
+  .x-axis .axis-numbers div {
     width: var(--cell-d-x);
     /* 与网格列宽一致 */
     text-align: center;
     color: #333;
-}
-
-/* 网格系统 */
-.grid-container {
+  }
+  
+  /* 网格系统 */
+  .grid-container {
     position: relative;
     margin-left: 30px;
     /* 与Y轴对齐 */
-
-}
-
-/* 网格内容 */
-.grid-content {
+  
+  }
+  
+  /* 网格内容 */
+  .grid-content {
     position: relative;
     z-index: 2;
-}
-
-.grid-row {
+  }
+  
+  .grid-row {
     display: flex;
     height: var(--cell-y);
     /* 固定行高上列下行 */
     gap: var(--cell-x);
-}
-
-.grid-item {
-
+  }
+  
+  .grid-item {
+  
     width: var(--cell-d);
     /* 固定宽度 */
     height: var(--cell-d);
-
+  
     background: transparent;
     transition: transform 0.2s;
-
-}
-
-
-
-.q-btn:hover {
+  
+  }
+  
+  
+  
+  .select-item:hover {
     transform: translateY(-2px);
     box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
-}
-
-
-</style>
+  }
+  
+  
+  </style>

+ 165 - 161
templates/src/pages/stock/stockbinlist.vue

@@ -1,5 +1,6 @@
 <template>
-  <div>
+  <div >
+
     <transition appear enter-active-class="animated fadeIn">
       <q-table class="my-sticky-header-column-table shadow-24" :data="table_list" row-key="id" :separator="separator"
         :loading="loading" :filter="filter" :columns="columns" hide-bottom :pagination.sync="pagination"
@@ -21,20 +22,24 @@
         </template>
         <template v-slot:body="props">
           <q-tr :props="props">
-            <q-td key="shelf_name" :props="props">{{ props.row.warehouse_name}}</q-td>
-            <q-td key="goods_code" :props="props">{{ props.row.goods_code }}</q-td>
-            <q-td key="goods_name" :props="props">{{ props.row.goods_name }}</q-td>
-            <q-td key="goods_in" :props="props">{{ props.row.goods_in }}</q-td>
-            <q-td key="goods_out" :props="props">{{ props.row.goods_out }}</q-td>
-            <q-td key="goods_qty" :props="props">{{ props.row.goods_qty}}</q-td>
-            <q-td key="action" :props="props" style="width: 50px">
-              <!-- <q-btn
-                v-show="$q.localStorage.getItem('staff_type') !== 'Inbound' && $q.localStorage.getItem('staff_type') !== 'Outbound'"
-                round flat push color="purple" icon="move_to_inbox" @click="BinMove(props.row)">
-                <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
-                  content-style="font-size: 12px">{{ $t('movetobin') }}</q-tooltip>
-              </q-btn> -->
-            </q-td>
+            <q-td key="detail" :props="props">
+                <q-btn round flat push color="black" icon="description" @click="detailData(props.row)">
+                  <q-tooltip content-class="bg-amber text-black shadow-4" :offset="[10, 10]"
+                    content-style="font-size: 12px">{{ "查看库位详情" }}</q-tooltip>
+                </q-btn>
+              </q-td>
+            <q-td key="location_items" :props="props">{{  }}</q-td>
+            <q-td key="group_name" :props="props">{{ props.row.group_name }}</q-td>
+            <q-td key="group_code" :props="props">{{ props.row.group_code }}</q-td>
+            <q-td key="group_type" :props="props">{{ props.row.group_type }}</q-td>
+            <q-td key="max_capacity" :props="props">{{ props.row.max_capacity }}</q-td>
+            <q-td key="current_quantity" :props="props">{{ props.row.current_quantity }}</q-td>
+            <q-td key="current_goods_quantity" :props="props">{{ props.row.current_goods_quantity }}</q-td>
+            <q-td key="current_batch" :props="props">{{ props.row.current_batch }}</q-td>
+            <q-td key="current_goods_code" :props="props">{{ props.row.current_goods_code }}</q-td>
+            <q-td key="status" :props="props">{{ props.row.status }}</q-td>
+           
+       
           </q-tr>
         </template>
       </q-table>
@@ -42,7 +47,8 @@
     <template>
       <div v-show="max !== 0" class="q-pa-lg flex flex-center">
         <div>{{ total }} </div>
-        <q-pagination v-model="current" color="black" :max="max" :max-pages="6" boundary-links @click="getList()" />
+        <q-pagination v-model="current" color="black" :max="max" :max-pages="6" boundary-links
+          @click="getSearchList(current); paginationIpt = current" />
         <div>
           <input v-model="paginationIpt" @blur="changePageEnter" @keyup.enter="changePageEnter"
             style="width: 60px; text-align: center" />
@@ -52,163 +58,173 @@
         <q-btn flat push color="dark" :label="$t('no_data')"></q-btn>
       </div>
     </template>
-    <!-- <q-dialog v-model="moveForm">
-      <q-card class="shadow-24">
-        <q-bar class="bg-light-blue-10 text-white rounded-borders" style="height: 50px">
-          <div>{{ movedata.goods_code }} {{ $t('frombin') }} {{ movedata.bin_name }}</div>
-          <q-space />
-          <q-btn dense flat icon="close" v-close-popup>
-            <q-tooltip>{{ $t('index.close') }}</q-tooltip>
-          </q-btn>
-        </q-bar>
-        <q-card-section style="max-height: 325px; width: 400px" class="scroll">
-          <q-input dense outlined square debounce="500" v-model.number="movedata.move_qty" type="number"
-            :label="$t('stock.view_stocklist.goods_qty')" style="margin-bottom: 5px"
-            :rules="[val => (val && val > 0) || error1]" @keyup.enter="MoveToBinSubmit()">
-            <template v-slot:before>
-              <q-select dense outlined square use-input hide-selected fill-input v-model="movedata.move_to_bin"
-                :label="$t('warehouse.view_binset.bin_name')" :options="options" @filter="filterFn"
-                @keyup.enter="MoveToBinSubmit()">
-                <template v-slot:no-option>
-                  <q-item><q-item-section class="text-grey">No results</q-item-section></q-item>
-                </template>
-                <template v-if="movedata.move_to_bin" v-slot:append>
-                  <q-icon name="cancel" @click.stop="movedata.move_to_bin = ''" class="cursor-pointer" />
-                </template>
-              </q-select>
-            </template>
-          </q-input>
-        </q-card-section>
-        <div style="float: right; padding: 15px 15px 15px 0">
-          <q-btn color="white" text-color="black" style="margin-right: 25px" @click="MoveToBinCancel()">{{ $t('cancel')
-            }}</q-btn>
-          <q-btn color="primary" @click="MoveToBinSubmit()">{{ $t('submit') }}</q-btn>
-        </div>
-      </q-card>
-    </q-dialog> -->
+
   </div>
 </template>
 <router-view />
 
 <script>
-import { getauth, postauth } from 'boot/axios_request'
-import { SessionStorage, LocalStorage } from 'quasar'
+import { getauth, postauth, putauth, deleteauth } from 'boot/axios_request'
+import { date, exportFile, LocalStorage } from 'quasar'
+
 
 export default {
-  name: 'Pagestockbinlist',
+  name: 'Pageflowlist',
   data() {
     return {
+      createDate1: '',
+      createDate2: '',
+      date_range: '',
+      proxyDate: '',
+      date: '',
+      goods_code: '',
+      goods_desc: '',
       openid: '',
       login_name: '',
       authin: '0',
-      pathname: 'stock/bin/',
+      searchUrl: '',
+      pathname: 'bin/group/',
+      pathfilename: 'reportcenter/file/',
+
       pathname_previous: '',
       pathname_next: '',
       separator: 'cell',
       loading: false,
       height: '',
+      viewForm: false,
+      printObj: {
+        id: 'printMe',
+        popTitle: this.$t('inbound.asn')
+      },
       table_list: [],
-      bin_size_list: [],
-      bin_property_list: [],
-      warehouse_list: [],
+
       columns: [
-        { name: 'shelf_name', required: true, label: this.$t('warehouse.view_binset.bin_name'), align: 'center', field: 'bin_name' },
-        { name: 'goods_code', label: this.$t('stock.view_stocklist.goods_code'), field: 'goods_code', align: 'center' },
-        { name: 'goods_name', label: '商品名称', field: 'goods_name', align: 'center' },
-        { name: 'goods_in', label: '入库数量', field: 'goods_in', align: 'center' },
-        { name: 'goods_out', label: '出库数量', field: 'goods_in', align: 'center' },
-        { name: 'goods_qty', label: '当前数量', field: 'goods_qty', align: 'center' },
-        { name: 'action', label: this.$t('action'), align: 'ceter' }
+        { name :'detail',label:'库位详情', field: 'detail', align: 'center'},
+        { name: 'group_name', required: true, label: '库位组名称',  align: 'center', field: 'group_name' },
+        { name: 'group_code', label: '库位组编码', field: 'group_code', align: 'center' },
+        { name: 'group_type', label: '库位组类型', field: 'group_type', align: 'center' },
+        { name: 'max_capacity', label: '最大容量', field: 'max_capacity', align: 'center'},
+        { name: 'current_quantity', label: '当前托盘数', field: 'current_quantity', align: 'center' },
+        { name: 'current_goods_quantity', label: '当前货物数', field: 'current_goods_quantity', align: 'center' },
+        { name: 'current_batch', label: '当前批次', field: 'current_batch', align: 'center' },
+        { name: 'current_goods_code', label: '当前货物编码', field: 'current_goods_code', align: 'center' },
+        { name: 'status', label: '状态',field:'status',align: 'ceter' },
+        {name: 'operation', label: '操作', field: 'operation', align: 'center'}
       ],
       filter: '',
       pagination: {
         page: 1,
-        rowsPerPage: '30'
+        rowsPerPage: 11
       },
-      options: [],
-      moveForm: false,
-      movedata: {},
-      error1: this.$t('inbound.view_sortstock.error1'),
+      newForm: false,
+      newFormData: {
+        document_date: '',
+        document_number: '',
+        document_type: '',
+        business_type: '',
+        iout_type: '',
+        department: '',
+        warehouse_code: '',
+        warehouse_name: '',
+        goods_code: '',
+        goods_desc: '',
+        goods_std: '',
+        goods_batch: '',
+        in_batch: '',
+        out_batch: '',
+        goods_unit: '',
+        goods_in: '',
+        goods_out: '',
+        goods_notes: '',
+        creator: ''
+      },
+      editid: 0,
+      editFormData: {},
+      editMode: false,
+      deleteForm: false,
+      deleteid: 0,
+      bar_code: '',
+      error1: this.$t('goods.view_goodslist.error1'),
+
       current: 1,
       max: 0,
       total: 0,
-      paginationIpt: 1
+      paginationIpt: 1,
+
+
+    }
+
+  },
+  computed: {
+    interval() {
+      return this.$t('download_center.start') + ' - ' + this.$t('download_center.end')
     }
   },
   methods: {
-    getList() {
+    getList(params = {}) {
       var _this = this
-      if (LocalStorage.has('auth')) {
-        getauth(_this.pathname + '?page=' + '' + _this.current + '&shelf_type=storage', {})
-          .then(res => {
-            _this.table_list = res.results
-            _this.total = res.count
-            if (res.count === 0) {
-              _this.max = 0
-            } else {
-              if (Math.ceil(res.count / 30) === 1) {
-                _this.max = 0
-              } else {
-                _this.max = Math.ceil(res.count / 30)
-              }
-            }
+      _this.loading = true
+      // 合并基础参数
+      const baseParams = {
+        page: _this.current,
+        page_size: _this.pagination.rowsPerPage
+      }
 
-            _this.pathname_previous = res.previous
-            _this.pathname_next = res.next
-          })
-          .catch(err => {
-            _this.$q.notify({
-              message: err.detail,
-              icon: 'close',
-              color: 'negative'
-            })
+      // 创建URLSearchParams处理参数
+      const queryParams = new URLSearchParams({
+        ...baseParams,
+        ...params
+      })
+      console.log(queryParams)
+      // 过滤空值参数
+      Array.from(queryParams.entries()).forEach(([key, value]) => {
+        if (value === '' || value === null || value === undefined) {
+          queryParams.delete(key)
+        }
+      })
+
+      getauth(`${_this.pathname}?${queryParams}`)
+        .then(res => {
+          _this.table_list = res.results
+          _this.total = res.count
+          _this.max = Math.ceil(res.count / _this.pagination.rowsPerPage) || 0
+          _this.pathname_previous = res.previous
+          _this.pathname_next = res.next
+        })
+        .catch(err => {
+          _this.$q.notify({
+            message: err.detail,
+            icon: 'close',
+            color: 'negative'
           })
-      }
+        })
+        .finally(() => {
+          _this.loading = false
+        })
     },
-    changePageEnter(e) {
+    changePageEnter() {
       if (Number(this.paginationIpt) < 1) {
-        this.current = 1;
-        this.paginationIpt = 1;
+        this.current = 1
+        this.paginationIpt = 1
       } else if (Number(this.paginationIpt) > this.max) {
-        this.current = this.max;
-        this.paginationIpt = this.max;
+        this.current = this.max
+        this.paginationIpt = this.max
       } else {
-        this.current = Number(this.paginationIpt);
+        this.current = Number(this.paginationIpt)
       }
-      this.getList();
+      this.getSearchList(this.current)
     },
-    getSearchList() {
-      var _this = this
-      if (LocalStorage.has('auth')) {
-        _this.current = 1
-        _this.paginationIpt = 1
-        getauth(_this.pathname + '?goods_name__icontains=' + _this.filter + '&max_page=10000'  + '&shelf_type=storage', {})
-          .then(res => {
-            _this.table_list = res.results
-            _this.total = res.count
-            if (res.count === 0) {
-              _this.max = 0
-            } else {
-              if (Math.ceil(res.count / 30) === 1) {
-                _this.max = 0
-              } else {
-                _this.max = Math.ceil(res.count / 30)
-              }
-            }
 
-            _this.pathname_previous = res.previous
-            _this.pathname_next = res.next
-          })
-          .catch(err => {
-            _this.$q.notify({
-              message: err.detail,
-              icon: 'close',
-              color: 'negative'
-            })
-          })
-      } else {
-      }
+    // 带搜索条件加载
+    getSearchList(page = 1) {
+      this.current = page
+      this.paginationIpt = page
+      this.getList({
+        group_name__icontains: this.filter,
+
+      })
     },
+
     getListPrevious() {
       var _this = this
       if (LocalStorage.has('auth')) {
@@ -225,6 +241,7 @@ export default {
               color: 'negative'
             })
           })
+      } else {
       }
     },
     getListNext() {
@@ -244,39 +261,14 @@ export default {
               color: 'negative'
             })
           })
-      } else {
       }
     },
     reFresh() {
       var _this = this
-      _this.getList()
+      _this.getSearchList()
     },
-    filterFn(val, update, abort) {
-      var _this = this
-      if (val.length < 1) {
-        abort()
-        return
-      }
-      update(() => {
-        const needle = val.toLowerCase()
-        getauth('binset/?bin_name__icontains=' + needle)
-          .then(res => {
-            var binlist = []
-            res.results.forEach(detail => {
-              binlist.push(detail.bin_name)
-            })
-            SessionStorage.set('bin_name', binlist)
-            _this.options = SessionStorage.getItem('bin_name')
-          })
-          .catch(err => {
-            _this.$q.notify({
-              message: err.detail,
-              icon: 'close',
-              color: 'negative'
-            })
-          })
-      })
-    }
+
+  
   },
   created() {
     var _this = this
@@ -308,6 +300,18 @@ export default {
     }
   },
   updated() { },
-  destroyed() { }
+  destroyed() { },
+
 }
 </script>
+<style scoped>
+/* 添加在 <style> 中 */
+.q-date__calendar-item--selected {
+  transition: all 0.3s ease;
+  background-color: #1976d2 !important;
+}
+
+.q-date__range {
+  background-color: rgba(25, 118, 210, 0.1);
+}
+</style>

BIN
utils/__pycache__/page.cpython-38.pyc