views.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  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 .models import ContainerListModel,ContainerDetailModel,ContainerOperationModel,ContainerWCSModel
  11. from bound.models import BoundBatchModel,BoundDetailModel,BoundListModel
  12. # from .files import FileListRenderCN, FileDetailRenderCN
  13. from .serializers import ContainerDetailGetSerializer,ContainerDetailPostSerializer
  14. from .serializers import ContainerListGetSerializer,ContainerListPostSerializer
  15. from .serializers import ContainerOperationGetSerializer,ContainerOperationPostSerializer
  16. from .filter import ContainerDetailFilter,ContainerListFilter,ContainerOperationFilter
  17. # 以后添加模
  18. from warehouse.models import ListModel as warehouse
  19. from staff.models import ListModel as staff
  20. from rest_framework.permissions import AllowAny
  21. class ContainerListViewSet(viewsets.ModelViewSet):
  22. """
  23. retrieve:
  24. Response a data list(get)
  25. list:
  26. Response a data list(all)
  27. create:
  28. Create a data line(post)
  29. delete:
  30. Delete a data line(delete)
  31. """
  32. # authentication_classes = [] # 禁用所有认证类
  33. # permission_classes = [AllowAny] # 允许任意访问
  34. pagination_class = MyPageNumberPagination
  35. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  36. ordering_fields = ['id', "create_time", "update_time", ]
  37. filter_class = ContainerListFilter
  38. def get_project(self):
  39. try:
  40. id = self.kwargs.get('pk')
  41. return id
  42. except:
  43. return None
  44. def get_queryset(self):
  45. id = self.get_project()
  46. if self.request.user:
  47. if id is None:
  48. return ContainerListModel.objects.filter()
  49. else:
  50. return ContainerListModel.objects.filter( id=id)
  51. else:
  52. return ContainerListModel.objects.none()
  53. def get_serializer_class(self):
  54. if self.action in ['list', 'destroy','retrieve']:
  55. return ContainerListGetSerializer
  56. elif self.action in ['create', 'update']:
  57. return ContainerListPostSerializer
  58. else:
  59. return self.http_method_not_allowed(request=self.request)
  60. def create(self, request, *args, **kwargs):
  61. data = self.request.data
  62. order_month = str(timezone.now().strftime('%Y%m'))
  63. data['month'] = order_month
  64. data['last_operate'] = str(timezone.now())
  65. serializer = self.get_serializer(data=data)
  66. serializer.is_valid(raise_exception=True)
  67. serializer.save()
  68. headers = self.get_success_headers(serializer.data)
  69. return Response(serializer.data, status=200, headers=headers)
  70. def update(self, request, pk):
  71. qs = self.get_object()
  72. data = self.request.data
  73. serializer = self.get_serializer(qs, data=data)
  74. serializer.is_valid(raise_exception=True)
  75. serializer.save()
  76. headers = self.get_success_headers(serializer.data)
  77. return Response(serializer.data, status=200, headers=headers)
  78. class TaskViewSet(viewsets.ModelViewSet):
  79. """
  80. retrieve:
  81. Response a data list(get)
  82. list:
  83. Response a data list(all)
  84. create:
  85. Create a data line(post)
  86. delete:
  87. Delete a data line(delete)
  88. """
  89. pagination_class = MyPageNumberPagination
  90. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  91. ordering_fields = ['id', "create_time", "update_time", ]
  92. filter_class = ContainerListFilter
  93. def get_project(self):
  94. try:
  95. id = self.kwargs.get('pk')
  96. return id
  97. except:
  98. return None
  99. def get_queryset(self):
  100. id = self.get_project()
  101. if self.request.user:
  102. if id is None:
  103. return ContainerListModel.objects.filter()
  104. else:
  105. return ContainerListModel.objects.filter( id=id)
  106. else:
  107. return ContainerListModel.objects.none()
  108. def get_serializer_class(self):
  109. if self.action in ['list', 'destroy','retrieve']:
  110. return ContainerListGetSerializer
  111. elif self.action in ['create', 'update']:
  112. return ContainerListPostSerializer
  113. else:
  114. return self.http_method_not_allowed(request=self.request)
  115. def create(self, request, *args, **kwargs):
  116. data = self.request.data
  117. order_month = str(timezone.now().strftime('%Y%m'))
  118. data['month'] = order_month
  119. data['last_operate'] = str(timezone.now())
  120. serializer = self.get_serializer(data=data)
  121. serializer.is_valid(raise_exception=True)
  122. serializer.save()
  123. headers = self.get_success_headers(serializer.data)
  124. return Response(serializer.data, status=200, headers=headers)
  125. def update(self, request, pk):
  126. qs = self.get_object()
  127. data = self.request.data
  128. serializer = self.get_serializer(qs, data=data)
  129. serializer.is_valid(raise_exception=True)
  130. serializer.save()
  131. headers = self.get_success_headers(serializer.data)
  132. return Response(serializer.data, status=200, headers=headers)
  133. class ContainerWCSViewSet(viewsets.ModelViewSet):
  134. """
  135. retrieve:
  136. Response a data list(get)
  137. list:
  138. Response a data list(all)
  139. create:
  140. Create a data line(post)
  141. delete:
  142. Delete a data line(delete)
  143. """
  144. authentication_classes = [] # 禁用所有认证类
  145. permission_classes = [AllowAny] # 允许任意访问
  146. def get_container_wcs(self, request, *args, **kwargs):
  147. data = self.request.data
  148. container = data.get('container_number')
  149. current_location = data.get('current_location')
  150. container_obj = ContainerListModel.objects.filter(container_code=container).first()
  151. data_tosave = {}
  152. data_return={}
  153. if container_obj:
  154. data['container_code'] = container
  155. serializer = ContainerListPostSerializer(container_obj, data=data)
  156. serializer.is_valid(raise_exception=True)
  157. serializer.save()
  158. if current_location == container_obj.target_location:
  159. print('当前位置已是目标位置')
  160. data['message'] = '当前位置已是目标位置'
  161. data_return={
  162. 'code':'200',
  163. 'message':data['message'],
  164. 'data':data
  165. }
  166. else:
  167. print('当前位置不是目标位置')
  168. current_task = ContainerWCSModel.objects.filter(container=container, tasktype='inbound').first()
  169. if current_task:
  170. data['message'] = '当前任务已存在,再次下发'
  171. data_return={
  172. 'code':'200',
  173. 'message':data['message'],
  174. 'data':current_task.to_dict()
  175. }
  176. else:
  177. print('生成入库任务')
  178. data_tosave['container'] = container
  179. data_tosave['current_location'] = current_location
  180. data_tosave['month'] = str(timezone.now().strftime('%Y%m'))
  181. data_tosave['target_location']=container_obj.target_location
  182. data_tosave['tasktype'] = 'inbound'
  183. container_obj_month = ContainerWCSModel.objects.filter( month=data_tosave['month']).all()
  184. if container_obj_month:
  185. data_tosave['taskid'] = data_tosave['tasktype']+'-'+data_tosave['month']+'-'+str(container_obj_month.count()+1).zfill(4)
  186. else:
  187. data_tosave['taskid'] = data_tosave['tasktype']+'-'+data_tosave['month']+'-0001'
  188. data_tosave['message'] = '生成入库任务'
  189. data_tosave['container'] = container
  190. data_tosave['status'] = 103
  191. data_tosave['is_delete'] = False
  192. data_return={
  193. 'code':'200',
  194. 'message':data_tosave['message'],
  195. 'data':data_tosave
  196. }
  197. ContainerWCSModel.objects.create(**data_tosave)
  198. print('入库任务创建成功', data_tosave['taskid'])
  199. else:
  200. print('托盘编码不存在')
  201. data_return={
  202. 'code':'400',
  203. 'message':'托盘编码不存在',
  204. 'data':data
  205. }
  206. return Response(data_return)
  207. class ContainerDetailViewSet(viewsets.ModelViewSet):
  208. """
  209. retrieve:
  210. Response a data list(get)
  211. list:
  212. Response a data list(all)
  213. create:
  214. Create a data line(post)
  215. delete:
  216. Delete a data line(delete)
  217. """
  218. # authentication_classes = [] # 禁用所有认证类
  219. # permission_classes = [AllowAny] # 允许任意访问
  220. pagination_class = MyPageNumberPagination
  221. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  222. ordering_fields = ['id', "create_time", "update_time", ]
  223. filter_class = ContainerDetailFilter
  224. def get_project(self):
  225. try:
  226. id = self.kwargs.get('pk')
  227. return id
  228. except:
  229. return None
  230. def get_queryset(self):
  231. id = self.get_project()
  232. if self.request.user:
  233. if id is None:
  234. return ContainerDetailModel.objects.filter( is_delete=False)
  235. else:
  236. return ContainerDetailModel.objects.filter( id=id, is_delete=False)
  237. else:
  238. return ContainerDetailModel.objects.none()
  239. def get_serializer_class(self):
  240. if self.action in ['list', 'destroy','retrieve']:
  241. return ContainerDetailGetSerializer
  242. elif self.action in ['create', 'update']:
  243. return ContainerDetailPostSerializer
  244. else:
  245. return self.http_method_not_allowed(request=self.request)
  246. def create(self, request, *args, **kwargs):
  247. data = self.request.data
  248. order_month = str(timezone.now().strftime('%Y%m'))
  249. data['month'] = order_month
  250. container_code = data.get('container')
  251. batches = data.get('batches', []) # 确保有默认空列表
  252. print('扫描到的托盘编码', container_code)
  253. # 处理托盘对象
  254. container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
  255. if container_obj:
  256. data['container'] = container_obj.id
  257. print('托盘编码存在', data['container'])
  258. else:
  259. print('托盘编码不存在')
  260. serializer_list = ContainerListPostSerializer(data={'container_code': container_code})
  261. serializer_list.is_valid(raise_exception=True)
  262. serializer_list.save()
  263. data['container'] = serializer_list.data.get('id')
  264. # 循环处理每个批次
  265. for batch in batches:
  266. bound_number = batch.get('goods_code')
  267. goods_qty = batch.get('goods_qty')
  268. # 查询商品对象
  269. bound_obj = BoundBatchModel.objects.filter(bound_number=bound_number).first()
  270. if not bound_obj:
  271. # 如果商品不存在,返回错误,这里暂时在程序中进行提醒,后续需要改为前端弹窗提醒
  272. print(f"商品编码 {bound_number} 不存在")
  273. # 跳出此次循环
  274. continue
  275. # return Response({"error": f"商品编码 {bound_number} 不存在"}, status=400)
  276. # 3. 更新批次数据(根据业务规则)
  277. try:
  278. last_qty = bound_obj.goods_in_qty
  279. bound_obj.goods_in_qty += batch.get("goods_qty", 0)
  280. if bound_obj.goods_in_qty >= bound_obj.goods_qty:
  281. bound_obj.goods_in_qty = bound_obj.goods_qty
  282. bound_obj.status = 1 # 批次状态为组盘完成
  283. print('批次id',bound_obj.id)
  284. bound_detail_obj = BoundDetailModel.objects.filter(bound_batch=bound_obj.id).first()
  285. if bound_detail_obj:
  286. bound_detail_obj.status = 1
  287. bound_detail_obj.save()
  288. print('入库申请id',bound_detail_obj.bound_list_id)
  289. # 入库申请全部批次入库完成
  290. bound_batch_all = BoundDetailModel.objects.filter(bound_list=bound_detail_obj.bound_list_id).all()
  291. if bound_batch_all.count() == bound_batch_all.filter(status=1).count():
  292. bound_list_obj = BoundListModel.objects.filter(id=bound_detail_obj.bound_list_id).first()
  293. print('当前状态',bound_list_obj.bound_status)
  294. bound_list_obj.bound_status = 102
  295. print('更新状态',bound_list_obj.bound_status)
  296. bound_list_obj.save()
  297. print('入库申请全部批次组盘完成')
  298. else:
  299. print('入库申请部分批次组盘完成')
  300. else:
  301. bound_obj.status = 0
  302. bound_obj.save() # 保存到数据库
  303. # 创建托盘详情记录(每个批次独立)
  304. print('新增个数',bound_obj.goods_in_qty-last_qty)
  305. if bound_obj.goods_in_qty-last_qty == goods_qty:
  306. detail_data = {
  307. "container": data['container'], # 托盘ID
  308. "batch": bound_obj.id, # 外键关联批次
  309. "goods_code": bound_obj.goods_code,
  310. "goods_desc": bound_obj.goods_desc,
  311. "goods_qty": goods_qty,
  312. "goods_weight": bound_obj.goods_weight,
  313. "status": 1,
  314. "month": data['month'],
  315. "creater": data.get('creater', 'zl') # 默认值兜底
  316. }
  317. serializer = self.get_serializer(data=detail_data)
  318. serializer.is_valid(raise_exception=True)
  319. serializer.save() # 必须保存到数据库
  320. operate_data = {
  321. "month" : data['month'],
  322. "container": data['container'], # 托盘ID
  323. "operation_type" : 'container',
  324. "batch" : bound_obj.id, # 外键关联批次
  325. "goods_code": bound_obj.goods_code,
  326. "goods_desc": bound_obj.goods_desc,
  327. "goods_qty": goods_qty,
  328. "goods_weight": bound_obj.goods_weight,
  329. "operator": data.get('creater', 'zl'), # 默认值兜底
  330. "timestamp": timezone.now(),
  331. "from_location": "container",
  332. "to_location": "container",
  333. "memo": "入库PDA组盘,pda入库"+str(bound_obj.goods_code)+"数量"+str(goods_qty)
  334. }
  335. serializer_operate = ContainerOperationPostSerializer(data=operate_data)
  336. serializer_operate.is_valid(raise_exception=True)
  337. serializer_operate.save() # 必须保存到数据库
  338. elif bound_obj.goods_in_qty-last_qty > 0:
  339. print('批次数量不一致')
  340. detail_data = {
  341. "container": data['container'], # 托盘ID
  342. "batch": bound_obj.id, # 外键关联批次
  343. "goods_code": bound_obj.goods_code,
  344. "goods_desc": bound_obj.goods_desc,
  345. "goods_qty": bound_obj.goods_in_qty-last_qty,
  346. "goods_weight": bound_obj.goods_weight,
  347. "status": 1,
  348. "month": data['month'],
  349. "creater": data.get('creater', 'zl') # 默认值兜底
  350. }
  351. serializer = self.get_serializer(data=detail_data)
  352. serializer.is_valid(raise_exception=True)
  353. serializer.save() # 必须保存到数据库
  354. operate_data = {
  355. "month" : data['month'],
  356. "container": data['container'], # 托盘ID
  357. "operation_type" : 'container',
  358. "batch" : bound_obj.id, # 外键关联批次
  359. "goods_code": bound_obj.goods_code,
  360. "goods_desc": bound_obj.goods_desc,
  361. "goods_qty": bound_obj.goods_in_qty-last_qty,
  362. "goods_weight": bound_obj.goods_weight,
  363. "operator": data.get('creater', 'zl'), # 默认值兜底
  364. "timestamp": timezone.now(),
  365. "from_location": "container",
  366. "to_location": "container",
  367. "memo": "入库PDA组盘,(数量不一致)pda入库"+str(bound_obj.goods_code)+"数量"+str(goods_qty)
  368. }
  369. serializer_operate = ContainerOperationPostSerializer(data=operate_data)
  370. serializer_operate.is_valid(raise_exception=True)
  371. serializer_operate.save() # 必须保存到数据库
  372. else :
  373. print('重复组盘')
  374. except Exception as e:
  375. print(f"更新批次 {bound_number} 失败: {str(e)}")
  376. continue
  377. # 将处理后的数据返回(或根据业务需求保存到数据库)
  378. res_data={
  379. "code": "200",
  380. "msg": "Success Create",
  381. "data": data
  382. }
  383. return Response(res_data, status=200)
  384. def update(self, request, pk):
  385. qs = self.get_object()
  386. data = self.request.data
  387. serializer = self.get_serializer(qs, data=data)
  388. serializer.is_valid(raise_exception=True)
  389. serializer.save()
  390. headers = self.get_success_headers(serializer.data)
  391. return Response(serializer.data, status=200, headers=headers)
  392. class ContainerOperateViewSet(viewsets.ModelViewSet):
  393. """
  394. retrieve:
  395. Response a data list(get)
  396. list:
  397. Response a data list(all)
  398. create:
  399. Create a data line(post)
  400. delete:
  401. Delete a data line(delete)
  402. """
  403. # authentication_classes = [] # 禁用所有认证类
  404. # permission_classes = [AllowAny] # 允许任意访问
  405. pagination_class = MyPageNumberPagination
  406. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  407. ordering_fields = ['id', "timestamp" ]
  408. filter_class = ContainerOperationFilter
  409. def get_project(self):
  410. try:
  411. id = self.kwargs.get('pk')
  412. return id
  413. except:
  414. return None
  415. def get_queryset(self):
  416. id = self.get_project()
  417. if self.request.user:
  418. if id is None:
  419. return ContainerOperationModel.objects.filter( is_delete=False)
  420. else:
  421. return ContainerOperationModel.objects.filter( id=id, is_delete=False)
  422. else:
  423. return ContainerOperationModel.objects.none()
  424. def get_serializer_class(self):
  425. if self.action in ['list', 'destroy','retrieve']:
  426. return ContainerOperationGetSerializer
  427. elif self.action in ['create', 'update']:
  428. return ContainerOperationPostSerializer
  429. else:
  430. return self.http_method_not_allowed(request=self.request)
  431. def create(self, request, *args, **kwargs):
  432. data = self.request.data
  433. serializer = self.get_serializer(data=data)
  434. serializer.is_valid(raise_exception=True)
  435. serializer.save()
  436. headers = self.get_success_headers(serializer.data)
  437. return Response(serializer.data, status=200, headers=headers)
  438. def update(self, request, pk):
  439. qs = self.get_object()
  440. data = self.request.data
  441. serializer = self.get_serializer(qs, data=data)
  442. serializer.is_valid(raise_exception=True)
  443. serializer.save()
  444. headers = self.get_success_headers(serializer.data)
  445. return Response(serializer.data, status=200, headers=headers)