utils.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. from django.db.models import Sum, F
  2. from .models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel,ContainerWCSModel
  3. from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
  4. from .serializers import *
  5. from rest_framework.response import Response
  6. from rest_framework.views import APIView
  7. from django.utils import timezone
  8. from decimal import Decimal
  9. import logging
  10. logger = logging.getLogger(__name__)
  11. def update_container_category_for_container(container_id):
  12. """
  13. 按需更新单个托盘的分类和批次信息
  14. """
  15. try:
  16. container = ContainerListModel.objects.get(id=container_id)
  17. # 获取托盘所有有效物料详情
  18. details = container.details.filter(
  19. is_delete=False
  20. ).exclude(status=3).annotate(
  21. available_qty=F('goods_qty') - F('goods_out_qty')
  22. ).filter(available_qty__gt=0)
  23. # 计算总物料量
  24. total_qty = details.aggregate(total=Sum('available_qty'))['total'] or 0
  25. # 收集批次信息
  26. batch_info = []
  27. for detail in details:
  28. batch = detail.batch
  29. if batch:
  30. batch_info.append({
  31. "batch_id": batch.id,
  32. "check_status": batch.check_status,
  33. "bound_number": batch.bound_number,
  34. "qty": float(detail.available_qty) # 转换为 float
  35. })
  36. # 确定托盘分类
  37. if total_qty == 0:
  38. # 空盘
  39. category = 2 if container.status == 2 else 3 # 2=在库, 3=不在库
  40. else:
  41. # 有物料
  42. batch_count = details.values('batch').distinct().count()
  43. category = 0 if batch_count == 1 else 1 # 0=整盘, 1=散盘
  44. # 更新
  45. container.category = category
  46. container.batch_info = batch_info
  47. container.save(update_fields=['category', 'batch_info'])
  48. return True
  49. except Exception as e:
  50. logger.error(f"更新托盘分类时出错: {e}", exc_info=True)
  51. return False
  52. def batch_update_container_categories(container_ids):
  53. """
  54. 批量更新多个托盘的分类和批次信息
  55. """
  56. updated_count = 0
  57. error_ids = []
  58. for container_id in container_ids:
  59. try:
  60. container = ContainerListModel.objects.get(id=container_id)
  61. # 获取托盘所有有效物料详情
  62. details = container.details.filter(
  63. is_delete=False
  64. ).exclude(status=3).annotate(
  65. available_qty=F('goods_qty') - F('goods_out_qty')
  66. ).filter(available_qty__gt=0)
  67. # 计算总物料量
  68. total_qty = details.aggregate(total=Sum('available_qty'))['total'] or 0
  69. # 收集批次信息,合并批次数量
  70. batch_info = []
  71. batch_map = {}
  72. for detail in details:
  73. batch = detail.batch
  74. if batch:
  75. if batch.id in batch_map:
  76. batch_map[batch.id]['qty'] += float(detail.available_qty) # 转换为 float
  77. else:
  78. batch_map[batch.id] = {
  79. "batch_id": batch.id,
  80. "check_status": batch.check_status,
  81. "bound_number": batch.bound_number,
  82. "qty": float(detail.available_qty) # 转换为 float
  83. }
  84. batch_info = list(batch_map.values())
  85. # 确定托盘分类
  86. if total_qty == 0:
  87. # 空盘
  88. category = 2 if container.current_location not in ['N/A', '103','203'] else 3 # 2=在库, 3=不在库
  89. else:
  90. # 有物料
  91. batch_count = details.values('batch').distinct().count()
  92. category = 0 if batch_count == 1 else 1 # 0=整盘, 1=散盘
  93. # 更新
  94. container.category = category
  95. container.batch_info = batch_info
  96. container.save(update_fields=['category', 'batch_info'])
  97. updated_count += 1
  98. except Exception as e:
  99. logger.error(f"更新托盘 {container_id} 分类时出错: {e}", exc_info=True)
  100. error_ids.append(container_id)
  101. return {
  102. "updated": updated_count,
  103. "errors": error_ids,
  104. "total": len(container_ids)
  105. }
  106. def update_container_categories_task():
  107. """后台任务:更新所有托盘的分类和批次信息"""
  108. container_ids = ContainerListModel.objects.values_list('id', flat=True)
  109. result = batch_update_container_categories(list(container_ids))
  110. print(f"后台任务更新托盘分类: 成功 {result['updated']}, 失败 {len(result['errors'])}")
  111. logger.info(f"后台任务更新托盘分类: 成功 {result['updated']}, 失败 {len(result['errors'])}")
  112. return result