|
@@ -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) # 更新新物料(全量刷新)
|
|
|
|
|
|
|
|
|
|