queries.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. from django.db import models
  2. from .models import *
  3. from django.db.models import Q
  4. import json
  5. from django.db import transaction
  6. from container.models import *
  7. from .models import LocationGroupModel
  8. import logging
  9. from collections import defaultdict
  10. logger = logging.getLogger(__name__)
  11. class LocationQueries:
  12. """"
  13. 库位相关查询
  14. functions:
  15. get_container(container_code): 获取托盘信息
  16. params: container_code: 托盘编号
  17. return: ContainerListModel
  18. get_active_container_details(container_id): 获取托盘详情
  19. params: container_id: 托盘ID
  20. return: ContainerDetailModel
  21. get_active_container_details(container_id): 获取托盘详情
  22. params: container_id: 托盘ID
  23. return: ContainerDetailModel
  24. get_batch_info(container_code): 获取托盘批次信息
  25. params: container_code: 托盘编号
  26. return: dict
  27. get_group_capacity(): 获取库位组空闲容量
  28. return: list
  29. get_current_pressure(): 获取仓库当前工作压力
  30. return: list
  31. get_pallet_count(container_code): 获取托盘数量
  32. params: container_code: 托盘编号
  33. return: int
  34. """
  35. @staticmethod
  36. def get_container(container_code):
  37. return ContainerListModel.objects.filter(container_code=container_code).first()
  38. @staticmethod
  39. def get_active_container_details(container_id):
  40. return ContainerDetailModel.objects.filter(
  41. container=container_id,is_delete=False
  42. ).exclude(status=3).first()
  43. @staticmethod
  44. def get_batch_info(container_code):
  45. container = ContainerListModel.objects.filter(
  46. container_code=container_code
  47. ).first()
  48. detail = ContainerDetailModel.objects.filter(
  49. container=container.id,is_delete=False
  50. ).exclude(status=3).first()
  51. if not detail:
  52. return {
  53. 'status': None,
  54. 'number': 'ContainerGroup'+str(container_code)+str(timezone.now().strftime('%Y%m%d')),
  55. 'container': container,
  56. 'class': 2 ,
  57. }
  58. elif detail.batch is None:
  59. return {
  60. 'status': None,
  61. 'number': 'ContainerGroup'+str(container_code)+str(timezone.now().strftime('%Y%m%d')),
  62. 'container': container,
  63. 'class': 2,
  64. }
  65. else:
  66. detail_all = ContainerDetailModel.objects.filter(
  67. container=container.id,is_delete=False
  68. ).exclude(status=3).all()
  69. # 统计该拖盘上的不同批次数目
  70. batch_count = len(set([item.batch.id for item in detail_all]))
  71. if batch_count > 1:
  72. return {
  73. 'status': None,
  74. 'number': 'ContainerScattered'+str(container_code)+str(timezone.now().strftime('%Y%m%d')),
  75. 'container': container,
  76. 'class': 3,
  77. }
  78. else:
  79. return {
  80. 'status': detail.batch.status ,
  81. 'number': detail.batch.bound_number ,
  82. 'container': container,
  83. 'class': 1,
  84. }
  85. @staticmethod
  86. def get_group_capacity():
  87. groups = ['T1', 'T2', 'S4', 'T4', 'T5']
  88. capacity = []
  89. for layer in [1, 2, 3]:
  90. layer_data = {}
  91. for group in groups:
  92. count = LocationGroupModel.objects.filter(
  93. group_type=group,
  94. layer=layer,
  95. status='available'
  96. ).count()
  97. layer_data[group] = count
  98. capacity.append(layer_data)
  99. return capacity
  100. @staticmethod
  101. def get_current_pressure():
  102. pressure = base_location.objects.first()
  103. if not pressure:
  104. pressure = base_location.objects.create()
  105. return [pressure.layer1_pressure, pressure.layer2_pressure, pressure.layer3_pressure]
  106. @staticmethod
  107. def get_pallet_count(container_code):
  108. """
  109. 获取托盘数量
  110. :param container_code: 要查询的托盘码
  111. :return: 所属批次下的托盘总数
  112. """
  113. # 1. 通过托盘码获取托盘详情
  114. container = ContainerListModel.objects.filter(
  115. container_code=container_code
  116. ).first()
  117. if not container:
  118. logger.error(f"托盘 {container_code} 不存在")
  119. return None
  120. container_detail = ContainerDetailModel.objects.filter(
  121. container=container.id,is_delete=False
  122. ).exclude(status = 3).first()
  123. batch_obj = container_detail.batch
  124. return batch_obj.container_number
  125. @staticmethod
  126. def get_pallet_count_by_batch(container_code):
  127. """
  128. 根据托盘码查询批次下托盘总数
  129. :param container_code: 要查询的托盘码
  130. :return: 所属批次下的托盘总数
  131. """
  132. # 1. 通过托盘码获取托盘详情
  133. container = ContainerListModel.objects.filter(
  134. container_code=container_code
  135. ).first()
  136. if not container:
  137. logger.error(f"托盘 {container_code} 不存在")
  138. return None
  139. container_detail = ContainerDetailModel.objects.filter(
  140. container=container.id,is_delete=False
  141. ).exclude(status = 3).first()
  142. if not container_detail:
  143. logger.error(f"托盘 {container_code} 未组盘")
  144. return None
  145. batch_container = ContainerDetailModel.objects.filter(
  146. batch = container_detail.batch.id,is_delete=False
  147. ).all().exclude(status = 3)
  148. # 统计批次下的不同托盘 item.contianer_id
  149. batch_container_count = 0
  150. container_ids = []
  151. for item in batch_container:
  152. if item.container_id not in container_ids:
  153. batch_container_count = batch_container_count + 1
  154. container_ids.append(item.container_id)
  155. batch_container_scatter = ContainerDetailModel.objects.filter(
  156. batch = container_detail.batch.id,is_delete=False,goods_class=3
  157. ).all().exclude(status = 3)
  158. batch_container_scatter_count = 0
  159. container_scatter_ids = []
  160. for item in batch_container_scatter:
  161. if item.container_id not in container_scatter_ids:
  162. batch_container_scatter_count = batch_container_scatter_count + 1
  163. container_scatter_ids.append(item.container_id)
  164. return batch_container_count,batch_container_scatter_count
  165. @staticmethod
  166. def get_current_finish_task(container,batch_info):
  167. batch = batch_info.get('number')
  168. if not batch:
  169. return None
  170. solution = alloction_pre.objects.filter(batch_number=batch).first()
  171. if not solution:
  172. return [0,0,0]
  173. return [solution.layer1_task_finish_number,solution.layer2_task_finish_number,solution.layer3_task_finish_number]
  174. @staticmethod
  175. def divide_solution_by_layer(data):
  176. # 统计所有存在的层级
  177. layer_counts = defaultdict(lambda: defaultdict(int))
  178. existing_layers = set()
  179. for item in data:
  180. # 分割层级和类型
  181. try:
  182. layer, loc_type = item.split('_')
  183. layer_num = int(layer)
  184. existing_layers.add(layer_num)
  185. layer_counts[layer_num][loc_type] += 1
  186. except (ValueError, IndexError):
  187. continue # 跳过无效格式的数据
  188. # 确定最大层级(至少包含1层)
  189. max_layer = max(existing_layers) if existing_layers else 1
  190. # 构建包含所有层级的最终结果
  191. final_result = {}
  192. for layer in range(1, max_layer + 1):
  193. final_result[str(layer)] = dict(layer_counts.get(layer, {}))
  194. return json.dumps(final_result, indent=2)
  195. @staticmethod
  196. def get_alloction_pre_solution(batch_number):
  197. """
  198. 获取指定批次的预留方案
  199. :param batch_number: 批次号
  200. :return: 预留方案
  201. """
  202. solution = alloction_pre.objects.filter(batch_number=batch_number).first()
  203. if not solution:
  204. return None
  205. return solution.layer_solution_type
  206. @staticmethod
  207. def get_left_location_group(batch_number):
  208. """
  209. 获取指定批次的剩余库位
  210. :param batch_number: 批次号
  211. :return: 剩余库位
  212. x ('available', '可用'),
  213. ('occupied', '占用'),
  214. x ('full', '满'),
  215. x ('disabled', '禁用'),
  216. ('reserved', '预留'),
  217. x ('maintenance', '维护中')
  218. """
  219. layer_solution_type =[]
  220. location_group_obj = LocationGroupModel.objects.filter(current_batch=batch_number).exclude(status__in=['available', 'full', 'disabled', 'maintenance'])
  221. if not location_group_obj:
  222. return None
  223. else:
  224. for item in location_group_obj:
  225. layer_solution_type.append(f"{item.layer}_{item.id}")
  226. return layer_solution_type