queries.py 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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': None,
  55. 'container': container,
  56. 'class': 2 ,
  57. }
  58. elif detail.batch is None:
  59. return {
  60. 'status': None,
  61. 'number': None,
  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. for item in detail_all:
  73. item.goods_class = 3
  74. item.save()
  75. return {
  76. 'status': None,
  77. 'number': None,
  78. 'container': container,
  79. 'class': 3,
  80. }
  81. else:
  82. return {
  83. 'status': detail.batch.status ,
  84. 'number': detail.batch.bound_number ,
  85. 'container': container,
  86. 'class': 1,
  87. }
  88. @staticmethod
  89. def get_group_capacity():
  90. groups = ['T1', 'T2', 'S4', 'T4', 'T5']
  91. capacity = []
  92. for layer in [1, 2, 3]:
  93. layer_data = {}
  94. for group in groups:
  95. count = LocationGroupModel.objects.filter(
  96. group_type=group,
  97. layer=layer,
  98. status='available'
  99. ).count()
  100. layer_data[group] = count
  101. capacity.append(layer_data)
  102. return capacity
  103. @staticmethod
  104. def get_current_pressure():
  105. pressure = base_location.objects.first()
  106. if not pressure:
  107. pressure = base_location.objects.create()
  108. return [pressure.layer1_pressure, pressure.layer2_pressure, pressure.layer3_pressure]
  109. @staticmethod
  110. def get_pallet_count(container_code):
  111. """
  112. 获取托盘数量
  113. :param container_code: 要查询的托盘码
  114. :return: 所属批次下的托盘总数
  115. """
  116. # 1. 通过托盘码获取托盘详情
  117. container = ContainerListModel.objects.filter(
  118. container_code=container_code
  119. ).first()
  120. if not container:
  121. logger.error(f"托盘 {container_code} 不存在")
  122. return None
  123. container_detail = ContainerDetailModel.objects.filter(
  124. container=container.id,is_delete=False
  125. ).exclude(status = 3).first()
  126. batch_obj = container_detail.batch
  127. return batch_obj.container_number
  128. @staticmethod
  129. def get_pallet_count_by_batch(container_code):
  130. """
  131. 根据托盘码查询批次下托盘总数
  132. :param container_code: 要查询的托盘码
  133. :return: 所属批次下的托盘总数
  134. """
  135. # 1. 通过托盘码获取托盘详情
  136. container = ContainerListModel.objects.filter(
  137. container_code=container_code
  138. ).first()
  139. if not container:
  140. logger.error(f"托盘 {container_code} 不存在")
  141. return None
  142. container_detail = ContainerDetailModel.objects.filter(
  143. container=container.id,is_delete=False
  144. ).exclude(status = 3).first()
  145. if not container_detail:
  146. logger.error(f"托盘 {container_code} 未组盘")
  147. return None
  148. batch_container = ContainerDetailModel.objects.filter(
  149. batch = container_detail.batch.id,is_delete=False
  150. ).all().exclude(status = 3)
  151. # 统计批次下的不同托盘 item.contianer_id
  152. batch_container_count = 0
  153. container_ids = []
  154. for item in batch_container:
  155. if item.container_id not in container_ids:
  156. batch_container_count = batch_container_count + 1
  157. container_ids.append(item.container_id)
  158. batch_container_scatter = ContainerDetailModel.objects.filter(
  159. batch = container_detail.batch.id,is_delete=False,goods_class=3
  160. ).all().exclude(status = 3)
  161. batch_container_scatter_count = 0
  162. container_scatter_ids = []
  163. for item in batch_container_scatter:
  164. if item.container_id not in container_scatter_ids:
  165. batch_container_scatter_count = batch_container_scatter_count + 1
  166. container_scatter_ids.append(item.container_id)
  167. return batch_container_count,batch_container_scatter_count
  168. @staticmethod
  169. def get_current_finish_task(container,batch_info):
  170. batch = batch_info.get('number')
  171. if not batch:
  172. return None
  173. solution = alloction_pre.objects.filter(batch_number=batch).first()
  174. if not solution:
  175. return [0,0,0]
  176. return [solution.layer1_task_finish_number,solution.layer2_task_finish_number,solution.layer3_task_finish_number]
  177. @staticmethod
  178. def divide_solution_by_layer(data):
  179. # 统计所有存在的层级
  180. layer_counts = defaultdict(lambda: defaultdict(int))
  181. existing_layers = set()
  182. for item in data:
  183. # 分割层级和类型
  184. try:
  185. layer, loc_type = item.split('_')
  186. layer_num = int(layer)
  187. existing_layers.add(layer_num)
  188. layer_counts[layer_num][loc_type] += 1
  189. except (ValueError, IndexError):
  190. continue # 跳过无效格式的数据
  191. # 确定最大层级(至少包含1层)
  192. max_layer = max(existing_layers) if existing_layers else 1
  193. # 构建包含所有层级的最终结果
  194. final_result = {}
  195. for layer in range(1, max_layer + 1):
  196. final_result[str(layer)] = dict(layer_counts.get(layer, {}))
  197. return json.dumps(final_result, indent=2)
  198. @staticmethod
  199. def get_alloction_pre_solution(batch_number):
  200. """
  201. 获取指定批次的预留方案
  202. :param batch_number: 批次号
  203. :return: 预留方案
  204. """
  205. solution = alloction_pre.objects.filter(batch_number=batch_number).first()
  206. if not solution:
  207. return None
  208. return solution.layer_solution_type
  209. @staticmethod
  210. def get_left_location_group(batch_number):
  211. """
  212. 获取指定批次的剩余库位
  213. :param batch_number: 批次号
  214. :return: 剩余库位
  215. x ('available', '可用'),
  216. ('occupied', '占用'),
  217. x ('full', '满'),
  218. x ('disabled', '禁用'),
  219. ('reserved', '预留'),
  220. x ('maintenance', '维护中')
  221. """
  222. layer_solution_type =[]
  223. location_group_obj = LocationGroupModel.objects.filter(current_batch=batch_number).exclude(status__in=['available', 'full', 'disabled', 'maintenance'])
  224. if not location_group_obj:
  225. return None
  226. else:
  227. for item in location_group_obj:
  228. layer_solution_type.append(f"{item.layer}_{item.id}")
  229. return layer_solution_type