Browse Source

日志准备

flower_bs 4 ngày trước cách đây
mục cha
commit
c2ab10c7b2

+ 67 - 29
bound/models.py

@@ -1,7 +1,7 @@
 from django.db import models
 from erp.models import InboundBill, MaterialDetail, OutboundBill,OutMaterialDetail
 from django.db.models import Sum
-from django.db.models.signals import post_save, post_delete
+from django.db.models.signals import post_save, post_delete, pre_save
 from django.dispatch import receiver
 from decimal import Decimal
 class BoundListModel(models.Model):
@@ -154,36 +154,74 @@ class MaterialStatistics(models.Model):
         verbose_name_plural = "物料统计"
         ordering = ['goods_code']
 
+
+
+
+@receiver(pre_save, sender=BoundBatchModel)
+def store_original_goods_code(sender, instance, **kwargs):
+    """保存前记录原始物料编码(仅更新时生效)"""
+    if not instance.pk:  # 新建对象无原始值
+        return
+
+    try:
+        original = BoundBatchModel.objects.get(pk=instance.pk)
+        # 将原始值存储在实例属性中供post_save使用
+        instance._original_goods_code = original.goods_code  
+    except BoundBatchModel.DoesNotExist:
+        pass
+
 @receiver([post_save, post_delete], sender=BoundBatchModel)
 def update_material_statistics(sender, instance, **kwargs):
-    goods_code = instance.goods_code
-    stats, created = MaterialStatistics.objects.get_or_create(
-        goods_code=goods_code,
-        defaults={
-            'goods_desc': instance.goods_desc,
-            'goods_std': instance.goods_std or '待填写',
-            'goods_unit': instance.goods_unit or '待填写',
-        }
-    )
-    
-    # 更新物料信息为最新批次的信息(可选)
-    stats.goods_desc = instance.goods_desc
-    if instance.goods_std and instance.goods_std != '待填写':
-        stats.goods_std = instance.goods_std
-    if instance.goods_unit and instance.goods_unit != '待填写':
-        stats.goods_unit = instance.goods_unit
-    stats.save()
-
-    # 计算总数量
-    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()
+    # 处理删除/创建/更新操作的核心逻辑
+    def refresh_stats(target_goods_code, force_desc=False):
+        """刷新指定物料的统计数据"""
+        stats, created = MaterialStatistics.objects.get_or_create(
+            goods_code=target_goods_code,
+            defaults={
+                'goods_desc': instance.goods_desc,
+                'goods_std': instance.goods_std or '待填写',
+                'goods_unit': instance.goods_unit or '待填写',
+            }
+        )
+        
+        # 仅强制更新描述(用于当前物料)或新建时初始化
+        if force_desc or created:
+            stats.goods_desc = instance.goods_desc
+            if instance.goods_std and instance.goods_std != '待填写':
+                stats.goods_std = instance.goods_std
+            if instance.goods_unit and instance.goods_unit != '待填写':
+                stats.goods_unit = instance.goods_unit
+        
+        # 重新聚合统计数据(始终执行)
+        agg = BoundBatchModel.objects.filter(goods_code=target_goods_code).aggregate(
+            total=Sum('goods_in_location_qty'),
+            total_out=Sum('goods_out_qty')
+        )
+        stats.total_quantity = agg['total'] or 0
+        # 如果有出库统计字段需更新,可在此添加
+        stats.save()
+
+    # 情况1:删除操作直接更新当前物料
+    if kwargs.get('signal') == post_delete:
+        refresh_stats(instance.goods_code)
+        return
+
+    # 情况2:创建操作直接更新新物料
+    if kwargs.get('created'):
+        refresh_stats(instance.goods_code, force_desc=True)
+        return
+
+    # 情况3:更新操作(检测物料编码变更)
+    original_code = getattr(instance, '_original_goods_code', None)
+    current_code = instance.goods_code
+
+    # 物料编码未变化时仅更新当前物料
+    if original_code == current_code:
+        refresh_stats(current_code, force_desc=True)
+    # 物料编码变化时更新新旧两个物料
+    else:
+        refresh_stats(original_code)      # 更新旧物料(仅刷新数量)
+        refresh_stats(current_code, force_desc=True)  # 更新新物料(全量刷新)
 
 
 

+ 35 - 0
container/migrations/0026_batchlogmodel.py

@@ -0,0 +1,35 @@
+# Generated by Django 4.1.2 on 2025-07-22 20:03
+
+from decimal import Decimal
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('bound', '0024_alter_batchlogmodel_goods_qty_and_more'),
+        ('container', '0025_alter_containerdetaillogmodel_log_type'),
+    ]
+
+    operations = [
+        migrations.CreateModel(
+            name='batchLogModel',
+            fields=[
+                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+                ('log_type', models.CharField(choices=[('create', '创建'), ('update', '更新'), ('delete', '删除'), ('out', '出库'), ('cancel_out', '取消出库'), ('status_change', '状态变更')], max_length=20, verbose_name='日志类型')),
+                ('goods_code', models.CharField(max_length=50, verbose_name='货品编码')),
+                ('goods_desc', models.CharField(max_length=100, verbose_name='货品描述')),
+                ('old_goods_qty', models.DecimalField(blank=True, decimal_places=3, default=Decimal('0'), max_digits=10, null=True, verbose_name='原数量')),
+                ('new_goods_qty', models.DecimalField(blank=True, decimal_places=3, default=Decimal('0'), max_digits=10, null=True, verbose_name='新数量')),
+                ('create_time', models.DateTimeField(auto_now_add=True, verbose_name='创建时间')),
+                ('batch', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='logs', to='bound.boundbatchmodel')),
+            ],
+            options={
+                'verbose_name': '批次日志',
+                'verbose_name_plural': '批次日志',
+                'db_table': 'batch_log',
+                'ordering': ['-create_time'],
+            },
+        ),
+    ]

+ 18 - 0
container/migrations/0027_containerdetaillogmodel_tobatchlog.py

@@ -0,0 +1,18 @@
+# Generated by Django 4.1.2 on 2025-07-22 20:42
+
+from django.db import migrations, models
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('container', '0026_batchlogmodel'),
+    ]
+
+    operations = [
+        migrations.AddField(
+            model_name='containerdetaillogmodel',
+            name='tobatchlog',
+            field=models.BooleanField(default=False, verbose_name='是否转移到批次日志'),
+        ),
+    ]

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 51 - 1
container/models.py