views.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730
  1. from rest_framework import viewsets
  2. from utils.page import MyPageNumberPagination
  3. from utils.datasolve import sumOfList, transportation_calculate
  4. from utils.md5 import Md5
  5. from rest_framework.filters import OrderingFilter
  6. from django_filters.rest_framework import DjangoFilterBackend
  7. from rest_framework.response import Response
  8. from rest_framework.exceptions import APIException
  9. from django.utils import timezone
  10. from django.db import transaction
  11. import logging
  12. from rest_framework import status
  13. from .models import DeviceModel,LocationModel,LocationGroupModel,LocationContainerLink,LocationChangeLog,alloction_pre
  14. from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
  15. from .filter import DeviceFilter,LocationFilter,LocationContainerLinkFilter,LocationChangeLogFilter,LocationGroupFilter
  16. from .serializers import LocationListSerializer,LocationPostSerializer
  17. from .serializers import LocationGroupListSerializer,LocationGroupPostSerializer
  18. # 以后添加模块时,只需要在这里添加即可
  19. from rest_framework.permissions import AllowAny
  20. from container.models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,TaskModel
  21. logger = logging.getLogger(__name__)
  22. # 库位分配
  23. # 入库规则函数
  24. # 逻辑根据批次下的托盘数目来找满足区间范围的库位,按照优先级排序,
  25. class locationViewSet(viewsets.ModelViewSet):
  26. """
  27. retrieve:
  28. Response a data list(get)
  29. list:
  30. Response a data list(all)
  31. create:
  32. Create a data line(post)
  33. delete:
  34. Delete a data line(delete)
  35. """
  36. # authentication_classes = [] # 禁用所有认证类
  37. # permission_classes = [AllowAny] # 允许任意访问
  38. pagination_class = MyPageNumberPagination
  39. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  40. ordering_fields = ['id', "create_time", "update_time", ]
  41. filter_class = LocationFilter
  42. def get_project(self):
  43. try:
  44. id = self.kwargs.get('pk')
  45. return id
  46. except:
  47. return None
  48. def get_queryset(self):
  49. id = self.get_project()
  50. if self.request.user:
  51. if id is None:
  52. return LocationModel.objects.filter()
  53. else:
  54. return LocationModel.objects.filter( id=id)
  55. else:
  56. return LocationModel.objects.none()
  57. def get_serializer_class(self):
  58. if self.action == 'list':
  59. return LocationListSerializer
  60. elif self.action == 'update':
  61. return LocationPostSerializer
  62. elif self.action =='retrieve':
  63. return LocationListSerializer
  64. def update(self, request, *args, **kwargs):
  65. qs = self.get_object()
  66. data = self.request.data
  67. location_code = data.get('location_code')
  68. # 处理库位对象
  69. location_obj = LocationModel.objects.filter(location_code=location_code).first()
  70. if not location_obj:
  71. logger.info(f"库位 {location_code} 不存在")
  72. return Response(
  73. {'code': '400', 'message': '库位不存在', 'data': None},
  74. status=status.HTTP_400_BAD_REQUEST
  75. )
  76. else:
  77. data['id'] = location_obj.id
  78. logger.info(f"库位 {location_code} 已存在")
  79. serializer = self.get_serializer(qs, data=data)
  80. serializer.is_valid(raise_exception=True)
  81. serializer.save()
  82. headers = self.get_success_headers(serializer.data)
  83. self.handle_group_location_status(location_code,location_obj.location_group)
  84. return Response(serializer.data, status=200, headers=headers)
  85. def handle_group_location_status(self,location_code,location_group):
  86. """
  87. 处理库位组和库位的关联关系
  88. :param location_code: 库位编码
  89. :param location_group: 库位组编码
  90. :return:
  91. """
  92. # 1. 获取库位空闲状态的库位数目
  93. location_obj_number = LocationModel.objects.filter(
  94. location_group=location_group,
  95. status='available'
  96. ).all().count()
  97. # 2. 获取库位组对象
  98. logger.info(f"库位组 {location_group} 下的库位数目:{location_obj_number}")
  99. # 1. 获取库位和库位组的关联关系
  100. location_group_obj = LocationGroupModel.objects.filter(
  101. group_code=location_group
  102. ).first()
  103. if not location_group_obj:
  104. logger.info(f"库位组 {location_group} 不存在")
  105. return None
  106. else:
  107. if location_obj_number == 0:
  108. # 库位组库位已满,更新库位组状态为full
  109. location_group_obj.status = 'full'
  110. location_group_obj.save()
  111. elif location_obj_number < location_group_obj.max_capacity:
  112. location_group_obj.status = 'occupied'
  113. location_group_obj.save()
  114. else:
  115. location_group_obj.status = 'available'
  116. location_group_obj.save()
  117. class locationGroupViewSet(viewsets.ModelViewSet):
  118. """
  119. retrieve:
  120. Response a data list(get)
  121. list:
  122. Response a data list(all)
  123. create:
  124. Create a data line(post)
  125. delete:
  126. Delete a data line(delete)
  127. """
  128. # authentication_classes = [] # 禁用所有认证类
  129. # permission_classes = [AllowAny] # 允许任意访问
  130. pagination_class = MyPageNumberPagination
  131. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  132. ordering_fields = ['id', "create_time", "update_time", ]
  133. filter_class = LocationGroupFilter
  134. def get_project(self):
  135. try:
  136. id = self.kwargs.get('pk')
  137. return id
  138. except:
  139. return None
  140. def get_queryset(self):
  141. id = self.get_project()
  142. if self.request.user:
  143. if id is None:
  144. return LocationGroupModel.objects.filter()
  145. else:
  146. return LocationGroupModel.objects.filter(id=id)
  147. else:
  148. return LocationGroupModel.objects.none()
  149. def get_serializer_class(self):
  150. if self.action == 'list':
  151. return LocationGroupListSerializer
  152. elif self.action == 'update':
  153. return LocationGroupPostSerializer
  154. elif self.action =='retrieve':
  155. return LocationGroupListSerializer
  156. def update(self, request, *args, **kwargs):
  157. data = self.request.data
  158. order_month = str(timezone.now().strftime('%Y%m'))
  159. data['month'] = order_month
  160. group_code = data.get('group_code')
  161. # 处理库位组对象
  162. group_obj = LocationGroupModel.objects.filter(group_code=group_code).first()
  163. if group_obj:
  164. data['id'] = group_obj.id
  165. logger.info(f"库位组 {group_code} 已存在")
  166. else:
  167. logger.info(f"库位组 {group_code} 不存在,创建库位组对象")
  168. serializer_list = LocationGroupPostSerializer(data=data)
  169. serializer_list.is_valid(raise_exception=True)
  170. serializer_list.save()
  171. data['id'] = serializer_list.data.get('id')
  172. return Response(data, status=status.HTTP_201_CREATED)
  173. class LocationAllocation:
  174. # 入库规则函数
  175. # fun:get_pallet_count_by_batch: 根据托盘码查询批次下托盘总数
  176. # fun:get_left_locationGroup_number_by_type: 获取每层库位组剩余数量
  177. # fun:get_location_type: 根据托盘数目获取库位类型
  178. # fun:update_location_container_link: 更新库位和托盘的关联关系
  179. # fun:update_location_group_batch: 更新库位组的批次
  180. # fun:update_batch_status: 更新批次状态yes/no
  181. # fun:update_location_status: 更新库位状态和
  182. # fun:up
  183. # fun:get_batch_status: 获取批次状态
  184. # fun:get_batch: 获取批次
  185. # fun:get_location_list_remainder: 获取可用库位的c_number列表
  186. # fun:get_location_by_type_remainder: 根据库位类型获取库位
  187. # fun:get_location_by_type: 第一次入库,根据库位类型获取库位
  188. # fun:get_location_by_status: 根据库位状态获取库位
  189. @transaction.atomic
  190. def get_pallet_count_by_batch(self, container_code):
  191. """
  192. 根据托盘码查询批次下托盘总数
  193. :param container_code: 要查询的托盘码
  194. :return: 所属批次下的托盘总数
  195. """
  196. # 1. 通过托盘码获取容器详情
  197. container = ContainerListModel.objects.filter(
  198. container_code=container_code
  199. ).first()
  200. if not container:
  201. logger.error(f"托盘 {container_code} 不存在")
  202. print(f"托盘 {container_code} 不存在")
  203. return None
  204. # 2. 获取关联的批次明细
  205. container_detail = ContainerDetailModel.objects.filter(
  206. container=container.id,
  207. status=1
  208. ).first()
  209. if not container_detail:
  210. print (f"容器 {container_code} 未组盘")
  211. logger.error(f"容器 {container_code} 未组盘")
  212. return None
  213. else:
  214. print (f"容器 {container_code} 已组盘")
  215. batch_container = ContainerDetailModel.objects.filter(
  216. batch = container_detail.batch.id,
  217. status = 1
  218. ).all()
  219. # 统计批次下的不同托盘 item.contianer_id
  220. batch_container_count = 0
  221. container_ids = []
  222. for item in batch_container:
  223. if item.container_id not in container_ids:
  224. batch_container_count = batch_container_count + 1
  225. container_ids.append(item.container_id)
  226. batch_item = BoundBatchModel.objects.filter( bound_number = container_detail.batch.bound_number).first()
  227. if not batch_item:
  228. print(f"批次号获取失败!")
  229. return None
  230. batch_item.container_number = batch_container_count
  231. batch_item.save()
  232. return batch_container_count
  233. def get_left_locationGroup_number_by_type(self):
  234. """
  235. 获取每层库位组剩余数量
  236. :return:
  237. """
  238. try:
  239. # 定义库位组和层号
  240. group = ['T1', 'T2', 'S4', 'T4', 'T5']
  241. layer = [1, 2, 3]
  242. # 初始化结果列表,包含三个空字典对应三个层
  243. left_number = [{} for _ in layer]
  244. for item in group:
  245. for idx, layer_num in enumerate(layer):
  246. # 检查库位组是否存在(不考虑状态)
  247. exists = LocationGroupModel.objects.filter(
  248. group_type=item,
  249. layer=layer_num
  250. ).exists()
  251. if not exists:
  252. print(f"库位组 {item}_{layer_num} 不存在")
  253. left_number[idx][item] = 0
  254. else:
  255. # 统计可用状态的库位组数量
  256. count = LocationGroupModel.objects.filter(
  257. group_type=item,
  258. layer=layer_num,
  259. status='available'
  260. ).count()
  261. left_number[idx][item] = count
  262. return left_number
  263. except Exception as e:
  264. logger.error(f"获取库位组剩余数量失败:{str(e)}")
  265. print(f"获取库位组剩余数量失败:{str(e)}")
  266. return None
  267. def get_location_type(self,container_code):
  268. """
  269. :param container_code: 托盘码
  270. :return: 库位类型列表
  271. """
  272. batch = self.get_batch(container_code)
  273. if not batch:
  274. print(f"类型分配中批次号获取失败!")
  275. return None
  276. location_solution = alloction_pre.objects.filter(batch_number=batch).first()
  277. if not location_solution:
  278. # 1. 获取托盘码对应批次号下所有的托盘数目
  279. container_number = self.get_pallet_count_by_batch(container_code)
  280. print (f"该批次下托盘总数:{container_number}")
  281. # 2. 计算每层剩余的库位数目
  282. layer_number=self.get_pallet_count_by_batch()
  283. # 3. 查看最新库位分配方案
  284. location_solution_last = alloction_pre.objects.filter().order_by('-id').first()
  285. if not location_solution_last:
  286. layer1_pressure =0
  287. layer2_pressure =0
  288. layer3_pressure =0
  289. else:
  290. layer1_pressure = location_solution_last.layer1_pressure
  291. layer2_pressure = location_solution_last.layer2_pressure
  292. layer3_pressure = location_solution_last.layer3_pressure
  293. # 4. 根据工作压力和库位类型,使用贪心算法,(AGV只有两个库位,故只给考虑1 2 层工作压力,第三层仅作为1,2层的补充,不考虑压力)获取库位类型列表,完成任务之后更新压力/TODO:需要考虑库位类型和库位数量的关系
  294. if layer1_pressure <=layer2_pressure:
  295. print(f"库位类型:{location_type}")
  296. # 5. 保存库位分配方案
  297. alloction_pre.objects.create(
  298. batch_number=batch,
  299. layer1_pressure=layer1_pressure,
  300. layer2_pressure=layer2_pressure,
  301. layer3_pressure=layer3_pressure,
  302. location_type=','.join(location_type)
  303. )
  304. return location_type
  305. else:
  306. print(f"库位类型:{location_solution.location_type}")
  307. return location_solution.location_type.split(",")
  308. @transaction.atomic
  309. def update_location_container_link(self,location_code,container_code):
  310. """
  311. 更新库位和托盘的关联关系
  312. :param location_code: 库位编码
  313. :param container_code: 托盘编码
  314. :return:
  315. """
  316. try:
  317. # 1. 获取库位和托盘的关联关系
  318. location = LocationModel.objects.filter(
  319. location_code=location_code
  320. ).first()
  321. container = ContainerListModel.objects.filter(
  322. container_code=container_code
  323. ).first()
  324. # 2. 如果库位和托盘的关联关系不存在,创建新的关联关系
  325. if not LocationContainerLink.objects.filter(location=location).exists():
  326. location_container_link = LocationContainerLink(
  327. location=location,
  328. container=container
  329. )
  330. location_container_link.save()
  331. print(f"更新库位和托盘的关联关系成功!")
  332. return True
  333. # 3. 更新库位和托盘的关联关系
  334. else:
  335. LocationContainerLink.objects.filter(location=location).update(location=location, container=container)
  336. print(f"更新库位和托盘的关联关系成功!")
  337. return True
  338. except Exception as e:
  339. logger.error(f"更新库位和托盘的关联关系失败:{str(e)}")
  340. print(f"更新库位和托盘的关联关系失败:{str(e)}")
  341. return False
  342. def update_location_group_batch(self,location,container_code):
  343. """
  344. :param location: 库位对象
  345. :param container_code: 托盘码
  346. :return:
  347. """
  348. try:
  349. # 1. 获取库位组
  350. location_group = LocationGroupModel.objects.filter(
  351. group_code=location.location_group
  352. ).first()
  353. if not location_group:
  354. print(f"库位组获取失败!")
  355. return False
  356. # 2. 更新库位组的批次
  357. bound_number=self.get_batch(container_code)
  358. if not bound_number:
  359. print(f"批次号获取失败!")
  360. return False
  361. location_group.current_batch = bound_number
  362. location_group.save()
  363. print(f"更新库位组的批次成功!")
  364. return True
  365. except Exception as e:
  366. logger.error(f"更新库位组的批次失败:{str(e)}")
  367. print(f"更新库位组的批次失败:{str(e)}")
  368. return False
  369. def update_location_status(self,location_code,status):
  370. """
  371. 更新库位状态
  372. :param location_code: 库位编码
  373. :param status: 库位状态
  374. :return:
  375. """
  376. try:
  377. # 1. 获取库位
  378. location = LocationModel.objects.filter(
  379. location_code=location_code
  380. ).first()
  381. if not location:
  382. print(f"库位获取失败!")
  383. return False
  384. # 2. 更新库位状态
  385. location.status = status
  386. location.save()
  387. print(f"更新库位状态成功!")
  388. return True
  389. except Exception as e:
  390. logger.error(f"更新库位状态失败:{str(e)}")
  391. print(f"更新库位状态失败:{str(e)}")
  392. return False
  393. def update_location_group_status(self, location_code):
  394. """
  395. 更新库位组状态
  396. :param location_code: 库位编码
  397. :return:
  398. """
  399. try:
  400. # 1. 获取库位
  401. location = LocationModel.objects.filter(
  402. location_code=location_code
  403. ).first()
  404. if not location:
  405. print(f"库位获取失败!")
  406. return False
  407. # 2. 获取库位组
  408. location_group = LocationGroupModel.objects.filter(
  409. group_code=location.location_group
  410. ).first()
  411. if not location_group:
  412. print(f"库位组获取失败!")
  413. return False
  414. current=0
  415. for location_item in location_group.location_items.all():
  416. if location_item.status != 'available':
  417. current=current + 1
  418. # 3. 更新库位组状态
  419. if current == 0:
  420. location_group.status = 'available'
  421. elif current == location_group.max_capacity:
  422. location_group.status = 'full'
  423. else:
  424. location_group.status = 'occupied'
  425. location_group.current_goods_quantity = sum(
  426. [loc.current_quantity for loc in location_group.location_items.all()]
  427. )
  428. location_group.current_quantity = current
  429. location_group.save()
  430. print(f"更新库位组状态成功!")
  431. return True
  432. except Exception as e:
  433. logger.error(f"更新库位组状态失败:{str(e)}")
  434. print(f"更新库位组状态失败:{str(e)}")
  435. def update_batch_status(self,container_code,status):
  436. """
  437. 更新批次状态
  438. :param batch_id: 批次id
  439. :param status: 批次状态
  440. :return:
  441. """
  442. try:
  443. # 1. 通过托盘码获取容器详情
  444. container = ContainerListModel.objects.filter(
  445. container_code=container_code
  446. ).first()
  447. if not container:
  448. logger.error(f"托盘 {container_code} 不存在")
  449. print(f"托盘 {container_code} 不存在")
  450. return None
  451. # 2. 获取关联的批次明细
  452. container_detail = ContainerDetailModel.objects.filter(
  453. container=container.id,
  454. status=1
  455. ).first()
  456. if not container_detail:
  457. print (f"容器 {container_code} 未组盘")
  458. logger.error(f"容器 {container_code} 未组盘")
  459. return None
  460. else:
  461. print (f"容器 {container_code} 已组盘")
  462. # 3. 更新批次状态
  463. batch = container_detail.batch
  464. batch.status = status
  465. batch.save()
  466. print(f"更新批次状态成功!")
  467. return True
  468. except Exception as e:
  469. logger.error(f"更新批次状态失败:{str(e)}")
  470. print(f"更新批次状态失败:{str(e)}")
  471. return False
  472. def get_batch_status(self,container_code):
  473. """
  474. 获取批次状态
  475. :param container_code: 托盘码
  476. :return: 批次状态
  477. """
  478. # 1. 通过托盘码获取容器详情
  479. container = ContainerListModel.objects.filter(
  480. container_code=container_code
  481. ).first()
  482. if not container:
  483. logger.error(f"托盘 {container_code} 不存在")
  484. print(f"托盘 {container_code} 不存在")
  485. return None
  486. # 2. 获取关联的批次明细
  487. container_detail = ContainerDetailModel.objects.filter(
  488. container=container.id,
  489. status=1
  490. ).first()
  491. if not container_detail:
  492. print (f"容器 {container_code} 未组盘")
  493. logger.error(f"容器 {container_code} 未组盘")
  494. return None
  495. else:
  496. print (f"容器 {container_code} 已组盘")
  497. batch_status = container_detail.batch.status
  498. return batch_status
  499. def get_batch(self,container_code):
  500. """
  501. 获取批次
  502. :param container_code: 托盘码
  503. :return: 批次
  504. """
  505. # 1. 通过托盘码获取容器详情
  506. container = ContainerListModel.objects.filter(
  507. container_code=container_code
  508. ).first()
  509. if not container:
  510. logger.error(f"托盘 {container_code} 不存在")
  511. print(f"托盘 {container_code} 不存在")
  512. return None
  513. # 2. 获取关联的批次明细
  514. container_detail = ContainerDetailModel.objects.filter(
  515. container=container.id,
  516. status=1
  517. ).first()
  518. if not container_detail:
  519. print (f"容器 {container_code} 未组盘")
  520. logger.error(f"容器 {container_code} 未组盘")
  521. return None
  522. else:
  523. print (f"容器 {container_code} 已组盘")
  524. batch = container_detail.batch.bound_number
  525. return batch
  526. @transaction.atomic
  527. def get_location_list_remainder(self, location_list):
  528. """
  529. 获取可用库位的c_number列表
  530. :param location_list: 库位对象列表
  531. :return: 可用库位编号列表
  532. """
  533. if not location_list:
  534. return None
  535. min_c_number=1000
  536. min_c_number_index=1000
  537. for location in location_list:
  538. if location.status != 'available':
  539. continue
  540. if int(location.c_number)<min_c_number:
  541. min_c_number=int(location.c_number)
  542. min_c_number_index=location_list.index(location)
  543. if min_c_number_index==1000:
  544. return None
  545. else:
  546. return min_c_number_index
  547. @transaction.atomic
  548. def get_location_by_type_remainder(self, batch, layer):
  549. """
  550. 根据库位类型获取库位
  551. :param batch: 批次号
  552. :param layer: 层数限制
  553. :return: 符合条件的库位列表
  554. """
  555. # 获取符合条件的库位组并按优先级排序
  556. location_groups = LocationGroupModel.objects.filter(
  557. current_batch=batch,
  558. layer=layer,
  559. ).first()
  560. if not location_groups:
  561. return None
  562. # 合并所有库位组中的库位
  563. locations = []
  564. locations.extend(location_groups.location_items.all()) # 假设location_items是关联字段
  565. return locations if locations else None
  566. @transaction.atomic
  567. def get_location_by_type(self, location_type_list, start_location, layer):
  568. """
  569. 第一次入库,根据库位类型获取库位
  570. :param location_type_list: 库位类型列表
  571. :param start_location: 起始位置(决定优先级排序方式)
  572. :param layer: 层数限制
  573. :return: 符合条件的库位列表
  574. """
  575. # 获取符合条件的库位组并按优先级排序
  576. location_groups = LocationGroupModel.objects.filter(
  577. group_type__in=location_type_list,
  578. layer=layer,
  579. status='available'
  580. )
  581. # 根据起始位置选择排序字段
  582. if start_location == 'in1':
  583. ordered_groups = location_groups.order_by('left_priority')
  584. elif start_location == 'in2':
  585. ordered_groups = location_groups.order_by('right_priority')
  586. else:
  587. ordered_groups = location_groups.none()
  588. locations = []
  589. locations.extend(ordered_groups.first().location_items.all()) # 假设location_items是关联字段
  590. return locations if locations else None
  591. @transaction.atomic
  592. def get_location_by_status(self,container_code,start_location,layer):
  593. """
  594. 根据库位状态获取库位
  595. :param location_type: 库位类型
  596. :param start_location: 起始库位 if in1 优先考虑left_priority, if in2 优先考虑right_priority 就是获取库位组列表之后进行排序
  597. :param layer: 层数 限定层数
  598. :return: 库位列表
  599. """
  600. # 1. 获取批次状态 102 为已组盘 103 为部分入库 104 为全部入库
  601. status = self.get_batch_status(container_code)
  602. #
  603. if status == 1:
  604. # 2. 获取库位组
  605. print (f"第一次入库")
  606. location_type_list = self.get_location_type(container_code)
  607. print(f"库位类型:{location_type_list}")
  608. location_list = self.get_location_by_type(location_type_list,start_location,layer)
  609. print(f"库位列表:{location_list}")
  610. location_min_index = self.get_location_list_remainder(location_list)
  611. print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
  612. if not location_list[location_min_index]:
  613. # 库位已满,返回None
  614. return None
  615. else:
  616. return location_list[location_min_index]
  617. elif status == 2:
  618. print(f"部分入库")
  619. # 2. 获取库位组
  620. location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
  621. print(f"库位列表:{location_list}")
  622. location_min_index = self.get_location_list_remainder(location_list)
  623. print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
  624. if not location_list[location_min_index]:
  625. # 库位已满,返回None
  626. return None
  627. else:
  628. return location_list[location_min_index]
  629. elif status == 3:
  630. print(f"全部入库")
  631. # 2. 获取库位组
  632. location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
  633. return location_list
  634. """
  635. 根据库位状态清除库位
  636. :param container_code: 托盘码
  637. :param start_location: 起始库位 if in1 优先考虑left_priority, if in2 优先考虑right_priority 就是获取库位组列表之后进行排序
  638. :param layer: 层数 限定层数
  639. :return: 库位列表
  640. """
  641. # 1. 获取批次状态 102 为已组盘 103 为部分入库 104 为全部入库
  642. status = self.get_batch_status(container_code)
  643. #
  644. if status == 1:
  645. # 2. 获取库位组
  646. print (f"第一次入库")
  647. container_number = self.get_pallet_count_by_batch(container_code)
  648. print (f"该批次下托盘总数:{container_number}")
  649. location_type_list = self.get_location_type(container_number)
  650. print(f"库位类型:{location_type_list}")
  651. location_list = self.get_location_by_type(location_type_list,start_location,layer)
  652. print(f"库位列表:{location_list}")
  653. location_min_index = self.get_location_list_remainder(location_list)
  654. print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
  655. if not location_list[location_min_index]:
  656. # 库位已满,返回None
  657. return None
  658. else:
  659. location_code = location_list[location_min_index].location_code
  660. self.update_location_status(location_code,'occupied')
  661. return location_list[location_min_index]
  662. elif status == 2:
  663. print(f"部分入库")
  664. # 2. 获取库位组
  665. location_list = self.get_location_by_type_remainder(self.get_batch(container_code),layer)
  666. print(f"库位列表:{location_list}")
  667. location_min_index = 1
  668. print(f"库位安排到第{location_min_index+1}个库位:{location_list[location_min_index]}")
  669. if not location_list[location_min_index]:
  670. # 库位已满,返回None
  671. return None
  672. else:
  673. location_code = location_list[location_min_index].location_code
  674. self.update_location_status(location_code,'occupied')
  675. return location_list[location_min_index]