Преглед на файлове

Merge branch 'okyy' of http://47.108.237.40:7788/zhanglei/greater_wms into okyy

flower преди 3 дни
родител
ревизия
28b68d30d2
променени са 32 файла, в които са добавени 841 реда и са изтрити 49564 реда
  1. 0 3
      .idea/.gitignore
  2. 0 14
      .idea/goods_wms.iml
  3. 0 6
      .idea/inspectionProfiles/profiles_settings.xml
  4. 0 7
      .idea/misc.xml
  5. 0 8
      .idea/modules.xml
  6. 0 6
      .idea/vcs.xml
  7. 1 0
      .vscode/launch.json
  8. 1 0
      bin/urls.py
  9. 84 1
      bin/views.py
  10. 28 0
      bound/migrations/0022_boundbatchmodel_check_status_and_more.py
  11. 18 0
      bound/migrations/0023_alter_materialstatistics_total_quantity.py
  12. 15 1
      bound/models.py
  13. 0 12812
      logs/error.log
  14. 0 36190
      logs/server.log
  15. 0 1
      templates/dist/spa/css/14.e18d8a65.css
  16. 1 0
      templates/dist/spa/css/14.e45ece1e.css
  17. 1 0
      templates/dist/spa/css/3.6aff5645.css
  18. 0 1
      templates/dist/spa/css/3.d5df0e68.css
  19. 1 1
      templates/dist/spa/index.html
  20. 1 0
      templates/dist/spa/js/14.543009c4.js
  21. 0 1
      templates/dist/spa/js/14.612866ed.js
  22. 0 1
      templates/dist/spa/js/3.d126d207.js
  23. BIN
      templates/dist/spa/js/3.d126d207.js.gz
  24. 1 0
      templates/dist/spa/js/3.f96d7c9f.js
  25. BIN
      templates/dist/spa/js/3.f96d7c9f.js.gz
  26. 0 1
      templates/dist/spa/js/app.4f2b4b5c.js
  27. BIN
      templates/dist/spa/js/app.4f2b4b5c.js.gz
  28. 1 0
      templates/dist/spa/js/app.c84cfb56.js
  29. BIN
      templates/dist/spa/js/app.c84cfb56.js.gz
  30. 2 3
      templates/src/components/goodscard.vue
  31. 1 1
      templates/src/pages/inbound/predeliverystock.vue
  32. 685 506
      templates/src/pages/stock/management.vue

+ 0 - 3
.idea/.gitignore

@@ -1,3 +0,0 @@
-# 默认忽略的文件
-/shelf/
-/workspace.xml

+ 0 - 14
.idea/goods_wms.iml

@@ -1,14 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="PYTHON_MODULE" version="4">
-  <component name="NewModuleRootManager">
-    <content url="file://$MODULE_DIR$">
-      <excludeFolder url="file://$MODULE_DIR$/.venv" />
-    </content>
-    <orderEntry type="jdk" jdkName="Python 3.8 (greater_wms)" jdkType="Python SDK" />
-    <orderEntry type="sourceFolder" forTests="false" />
-  </component>
-  <component name="PyDocumentationSettings">
-    <option name="format" value="GOOGLE" />
-    <option name="myDocStringFormat" value="Google" />
-  </component>
-</module>

+ 0 - 6
.idea/inspectionProfiles/profiles_settings.xml

@@ -1,6 +0,0 @@
-<component name="InspectionProjectProfileManager">
-  <settings>
-    <option name="USE_PROJECT_PROFILE" value="false" />
-    <version value="1.0" />
-  </settings>
-</component>

+ 0 - 7
.idea/misc.xml

@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="Black">
-    <option name="sdkName" value="Python 3.10 (goods_wms)" />
-  </component>
-  <component name="ProjectRootManager" version="2" project-jdk-name="Python 3.8 (greater_wms)" project-jdk-type="Python SDK" />
-</project>

+ 0 - 8
.idea/modules.xml

@@ -1,8 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="ProjectModuleManager">
-    <modules>
-      <module fileurl="file://$PROJECT_DIR$/.idea/goods_wms.iml" filepath="$PROJECT_DIR$/.idea/goods_wms.iml" />
-    </modules>
-  </component>
-</project>

+ 0 - 6
.idea/vcs.xml

@@ -1,6 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project version="4">
-  <component name="VcsDirectoryMappings">
-    <mapping directory="" vcs="Git" />
-  </component>
-</project>

+ 1 - 0
.vscode/launch.json

@@ -1,6 +1,7 @@
 {
   "version": "0.2.0",
   "configurations": [
+    
 
     {
       "name": "Python: Django",

+ 1 - 0
bin/urls.py

@@ -3,6 +3,7 @@ from . import views
 
 urlpatterns = [
     path ('', views.locationViewSet.as_view({"get": "list"}), name='location_list'),
+    path ('check/', views.locationViewSet.as_view({"post": "batch_status_location"}), name='location_list'),
     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'),

+ 84 - 1
bin/views.py

@@ -140,7 +140,90 @@ class locationViewSet(viewsets.ModelViewSet):
             else:
                 location_group_obj.status = 'available'
                 location_group_obj.save()
-       
+
+    def batch_status_location(self, request):
+        """
+        优化版:批量获取库位批次状态
+        基于模型结构优化查询
+        """
+        layer = request.data.get('layer')
+        
+        # 使用反向关系名 'container_links' 进行预取
+        locations = LocationModel.objects.filter(
+            layer=layer
+        ).prefetch_related(
+            Prefetch(
+                'container_links',  # 使用模型定义的 related_name
+                queryset=LocationContainerLink.objects.filter(is_active=True)
+                                                        .select_related('container'),
+                to_attr='active_links'
+            )
+        )
+        
+        # 收集所有激活链接的容器ID
+        container_ids = set()
+        for loc in locations:
+            if loc.active_links:  # 每个库位最多只有一个激活链接
+                container_ids.add(loc.active_links[0].container_id)
+        
+        # 批量查询容器详情及其批次状态
+        container_batch_status = defaultdict(dict)  # 改为字典存储,避免重复记录
+        if container_ids:
+            container_details = ContainerDetailModel.objects.filter(
+                container_id__in=container_ids
+            ).select_related('batch').exclude(status=3)  # 排除已删除或不合格的托盘
+            
+            for detail in container_details:
+                if detail.batch_id:
+                    # 创建唯一标识的键
+                    status_key = (
+                        detail.batch.check_status if detail.batch else "404",
+                        detail.batch.bound_number if detail.batch else "no_batch"
+                    )
+                    
+                    # 如果这个状态尚未添加过,或者需要更新
+                    if status_key not in container_batch_status[detail.container_id]:
+                        container_batch_status[detail.container_id][status_key] = (
+                            detail.batch.check_status if detail.batch else "404",
+                            detail.batch.check_time if detail.batch else "no_check_time",
+                            detail.batch.bound_number if detail.batch else "no_batch"
+                        )
+        
+        # 构造返回数据
+        return_data = []
+        for loc in locations:
+            batch_statuses = []
+            
+            if loc.active_links:
+                container_id = loc.active_links[0].container_id
+                # 从字典中提取值并转换为列表
+                if container_id in container_batch_status:
+                    batch_statuses = list(container_batch_status[container_id].values())
+            else:
+                batch_statuses = [("404", "no_check_time", "no_batch")]
+            
+            # 使用Django模型自带的model_to_dict转换基础字段
+            from django.forms.models import model_to_dict
+            location_data = model_to_dict(loc, fields=[
+                "id", "shelf_type", "row", "col", "layer", "update_time", 
+                "empty_label", "location_code", "location_group", "location_type", 
+                "status", "max_capacity", "current_quantity", "c_number", 
+                "coordinate", "access_priority", "is_active"
+            ])
+            
+            # 添加批次状态字段 - 存储所有信息
+            location_data["batch_statuses"] = batch_statuses
+            
+            return_data.append(location_data)
+            data = {
+                "code": "200",
+                "msg": "Success Create",
+                "data": return_data
+            }
+        
+        return Response(data, status=200)
+        
+
 class locationGroupViewSet(viewsets.ModelViewSet):
     """
         retrieve:

+ 28 - 0
bound/migrations/0022_boundbatchmodel_check_status_and_more.py

@@ -0,0 +1,28 @@
+# Generated by Django 4.1.2 on 2025-06-23 13:09
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0021_alter_boundlistmodel_options'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='boundbatchmodel',
+            name='check_status',
+            field=models.IntegerField(choices=[(0, '未质检'), (1, '已质检'), (2, '质检不合格')], default=0, verbose_name='质检状态'),
+        ),
+        migrations.AddField(
+            model_name='boundbatchmodel',
+            name='check_time',
+            field=models.DateTimeField(auto_now=True, null=True, verbose_name='质检时间'),
+        ),
+        migrations.AddField(
+            model_name='boundbatchmodel',
+            name='check_user',
+            field=models.CharField(default='', max_length=255, verbose_name='质检人'),
+        ),
+    ]

+ 18 - 0
bound/migrations/0023_alter_materialstatistics_total_quantity.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-06-28 21:08
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0022_boundbatchmodel_check_status_and_more'),
+    ]
+
+    operations = [
+        migrations.AlterField(
+            model_name='materialstatistics',
+            name='total_quantity',
+            field=models.BigIntegerField(default=0, verbose_name='在库数量'),
+        ),
+    ]

+ 15 - 1
bound/models.py

@@ -55,6 +55,11 @@ class BoundBatchModel(models.Model):
         (6, '已出库'),
 
     )
+    CHECK_STATUS=(
+        (0, '未质检'),
+        (1, '已质检'),
+        (2, '质检不合格'),
+    )
 
     bound_number = models.CharField(max_length=255, verbose_name="入库批次号",blank=False, null=False, unique=True)
     sourced_number = models.CharField(max_length=255, verbose_name="来源批次号",blank=True, null=True)
@@ -87,6 +92,11 @@ class BoundBatchModel(models.Model):
     update_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="Update Time")
     relate_material = models.ForeignKey(MaterialDetail, on_delete=models.CASCADE, verbose_name="关联物料", related_name='bound_batch',null=True, blank=True)
     
+    check_status = models.IntegerField(choices=CHECK_STATUS, default=0, verbose_name='质检状态')
+    check_user = models.CharField(default='', max_length=255, verbose_name="质检人")
+    check_time = models.DateTimeField(auto_now=True, blank=True, null=True, verbose_name="质检时间")
+
+
     class Meta:
         db_table = 'boundbatch'
         verbose_name = 'Bound Batch'
@@ -128,7 +138,7 @@ class MaterialStatistics(models.Model):
     goods_desc = models.CharField(max_length=255, verbose_name="商品描述")
     goods_std = models.CharField(default='待填写', max_length=255, verbose_name="商品标准", blank=True, null=True)
     goods_unit = models.CharField(default='待填写', max_length=255, verbose_name="商品单位")
-    total_quantity = models.BigIntegerField(default=0, verbose_name="计划数量")
+    total_quantity = models.BigIntegerField(default=0, verbose_name="在库数量")
     total_demanded_quantity = models.BigIntegerField(default=0, verbose_name="需求数量")
 
     def __str__(self):
@@ -168,6 +178,10 @@ def update_material_statistics(sender, instance, **kwargs):
     total = BoundBatchModel.objects.filter(goods_code=goods_code).aggregate(
         total=Sum('goods_in_location_qty')
     )['total'] or 0
+    # 更新物料统计的出库数目
+    total_out = BoundBatchModel.objects.filter(goods_code=goods_code).aggregate(
+        total_out=Sum('goods_out_qty')
+    )['total_out'] or 0
     stats.total_quantity = total
     stats.save()
 

Файловите разлики са ограничени, защото са твърде много
+ 0 - 12812
logs/error.log


Файловите разлики са ограничени, защото са твърде много
+ 0 - 36190
logs/server.log


+ 0 - 1
templates/dist/spa/css/14.e18d8a65.css

@@ -1 +0,0 @@
-.q-date__calendar-item--selected[data-v-8a465e2c]{transition:all 0.3s ease;background-color:#1976d2!important}.q-date__range[data-v-8a465e2c]{background-color:rgba(25,118,210,0.1)}.custom-title[data-v-8a465e2c]{font-size:0.9rem;font-weight:500}.custom-timeline[data-v-8a465e2c]{--q-timeline-color:#e0e0e0}.custom-node .q-timeline__dot[data-v-8a465e2c]{background:#485573!important;border:2px solid #5c6b8c!important}.custom-node .q-timeline__content[data-v-8a465e2c]{color:#485573}

+ 1 - 0
templates/dist/spa/css/14.e45ece1e.css

@@ -0,0 +1 @@
+.q-date__calendar-item--selected[data-v-2edd28fc]{transition:all 0.3s ease;background-color:#1976d2!important}.q-date__range[data-v-2edd28fc]{background-color:rgba(25,118,210,0.1)}.custom-title[data-v-2edd28fc]{font-size:0.9rem;font-weight:500}.custom-timeline[data-v-2edd28fc]{--q-timeline-color:#e0e0e0}.custom-node .q-timeline__dot[data-v-2edd28fc]{background:#485573!important;border:2px solid #5c6b8c!important}.custom-node .q-timeline__content[data-v-2edd28fc]{color:#485573}

Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
templates/dist/spa/css/3.6aff5645.css


Файловите разлики са ограничени, защото са твърде много
+ 0 - 1
templates/dist/spa/css/3.d5df0e68.css


Файловите разлики са ограничени, защото са твърде много
+ 1 - 1
templates/dist/spa/index.html


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
templates/dist/spa/js/14.543009c4.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 1
templates/dist/spa/js/14.612866ed.js


Файловите разлики са ограничени, защото са твърде много
+ 0 - 1
templates/dist/spa/js/3.d126d207.js


BIN
templates/dist/spa/js/3.d126d207.js.gz


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
templates/dist/spa/js/3.f96d7c9f.js


BIN
templates/dist/spa/js/3.f96d7c9f.js.gz


Файловите разлики са ограничени, защото са твърде много
+ 0 - 1
templates/dist/spa/js/app.4f2b4b5c.js


BIN
templates/dist/spa/js/app.4f2b4b5c.js.gz


Файловите разлики са ограничени, защото са твърде много
+ 1 - 0
templates/dist/spa/js/app.c84cfb56.js


BIN
templates/dist/spa/js/app.c84cfb56.js.gz


+ 2 - 3
templates/src/components/goodscard.vue

@@ -482,6 +482,7 @@ export default {
       container_id: 123456,
       container_code: 0,
       results: [],
+      location_status_display: '库位空闲',
       storage_form: [],
       elevator_form: {
         ip: '',
@@ -646,8 +647,6 @@ export default {
         .toString()
         .padStart(2, '0')}-${loc.layer.toString().padStart(2, '0')}`
     },
-
-    
     showReleaseDialog () {
       if (this.container_code) {
         this.location_status_display = `托盘: ${this.container_code} - 占用中`
@@ -666,7 +665,7 @@ export default {
       try {
         const locationCode = this.formatLocation(this.current_location)
         const payload = {
-          location_release: locationCode,
+          location_release: locationCode
         }
 
         const response = await postauth('container/location_release/', payload)

+ 1 - 1
templates/src/pages/inbound/predeliverystock.vue

@@ -114,7 +114,7 @@
                           <div class="col">
                             <div class="custom-title">
                               预定/已出库数量:{{
-                                batch_item.goods_reserve_qty
+                                batch_item.goods_out_qty
                               }}
                             </div>
                           </div>

Файловите разлики са ограничени, защото са твърде много
+ 685 - 506
templates/src/pages/stock/management.vue