views.py 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  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 ContainerWCSViewSet(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. authentication_classes = [] # 禁用所有认证类
  90. permission_classes = [AllowAny] # 允许任意访问
  91. def get_container_wcs(self, request, *args, **kwargs):
  92. data = self.request.data
  93. container = data.get('container_number')
  94. current_location = data.get('current_location')
  95. container_obj = ContainerListModel.objects.filter(container_code=container).first()
  96. data_tosave = {}
  97. if container_obj:
  98. print('托盘编码存在', container_obj.id)
  99. data['container'] = container
  100. print('托盘编码存储', data['container'])
  101. if container_obj.current_location == container_obj.target_location:
  102. data['message'] = '当前位置已是目标位置'
  103. else:
  104. current_task = ContainerWCSModel.objects.filter(container=container, tasktype='inbound').first()
  105. if current_task:
  106. data['message'] = '当前任务已存在,再次下发'
  107. data_return={
  108. 'code':'200',
  109. 'message':data['message'],
  110. 'data':current_task.to_dict()
  111. }
  112. else:
  113. data_tosave['container'] = container
  114. data_tosave['current_location'] = current_location
  115. data_tosave['month'] = str(timezone.now().strftime('%Y%m'))
  116. data_tosave['target_location']=container_obj.target_location
  117. data_tosave['tasktype'] = 'inbound'
  118. container_obj_month = ContainerWCSModel.objects.filter( month=data_tosave['month']).all()
  119. if container_obj_month:
  120. data_tosave['taskid'] = data_tosave['tasktype']+'-'+data_tosave['month']+'-'+str(container_obj_month.count()+1).zfill(4)
  121. else:
  122. data_tosave['taskid'] = data_tosave['tasktype']+'-'+data_tosave['month']+'-0001'
  123. data_tosave['message'] = '生成入库任务'
  124. data_tosave['container'] = container
  125. data_tosave['status'] = 103
  126. data_return={
  127. 'code':'200',
  128. 'message':data_tosave['message'],
  129. 'data':data_tosave
  130. }
  131. ContainerWCSModel.objects.create(**data_tosave)
  132. print('入库任务创建成功', data_tosave['taskid'])
  133. else:
  134. print('托盘编码不存在')
  135. data_return={
  136. 'code':'400',
  137. 'message':'托盘编码不存在',
  138. 'data':data
  139. }
  140. return Response(data_return)
  141. class ContainerDetailViewSet(viewsets.ModelViewSet):
  142. """
  143. retrieve:
  144. Response a data list(get)
  145. list:
  146. Response a data list(all)
  147. create:
  148. Create a data line(post)
  149. delete:
  150. Delete a data line(delete)
  151. """
  152. # authentication_classes = [] # 禁用所有认证类
  153. # permission_classes = [AllowAny] # 允许任意访问
  154. pagination_class = MyPageNumberPagination
  155. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  156. ordering_fields = ['id', "create_time", "update_time", ]
  157. filter_class = ContainerDetailFilter
  158. def get_project(self):
  159. try:
  160. id = self.kwargs.get('pk')
  161. return id
  162. except:
  163. return None
  164. def get_queryset(self):
  165. id = self.get_project()
  166. if self.request.user:
  167. if id is None:
  168. return ContainerDetailModel.objects.filter( is_delete=False)
  169. else:
  170. return ContainerDetailModel.objects.filter( id=id, is_delete=False)
  171. else:
  172. return ContainerDetailModel.objects.none()
  173. def get_serializer_class(self):
  174. if self.action in ['list', 'destroy','retrieve']:
  175. return ContainerDetailGetSerializer
  176. elif self.action in ['create', 'update']:
  177. return ContainerDetailPostSerializer
  178. else:
  179. return self.http_method_not_allowed(request=self.request)
  180. def create(self, request, *args, **kwargs):
  181. data = self.request.data
  182. order_month = str(timezone.now().strftime('%Y%m'))
  183. data['month'] = order_month
  184. container_code = data.get('container')
  185. batches = data.get('batches', []) # 确保有默认空列表
  186. print('扫描到的托盘编码', container_code)
  187. # 处理托盘对象
  188. container_obj = ContainerListModel.objects.filter(container_code=container_code).first()
  189. if container_obj:
  190. data['container'] = container_obj.id
  191. print('托盘编码存在', data['container'])
  192. else:
  193. print('托盘编码不存在')
  194. serializer_list = ContainerListPostSerializer(data={'container_code': container_code})
  195. serializer_list.is_valid(raise_exception=True)
  196. serializer_list.save()
  197. data['container'] = serializer_list.data.get('id')
  198. # 循环处理每个批次
  199. for batch in batches:
  200. bound_number = batch.get('goods_code')
  201. goods_qty = batch.get('goods_qty')
  202. # 查询商品对象
  203. bound_obj = BoundBatchModel.objects.filter(bound_number=bound_number).first()
  204. if not bound_obj:
  205. # 如果商品不存在,返回错误,这里暂时在程序中进行提醒,后续需要改为前端弹窗提醒
  206. print(f"商品编码 {bound_number} 不存在")
  207. # 跳出此次循环
  208. continue
  209. # return Response({"error": f"商品编码 {bound_number} 不存在"}, status=400)
  210. # 3. 更新批次数据(根据业务规则)
  211. try:
  212. last_qty = bound_obj.goods_in_qty
  213. bound_obj.goods_in_qty += batch.get("goods_qty", 0)
  214. if bound_obj.goods_in_qty >= bound_obj.goods_qty:
  215. bound_obj.goods_in_qty = bound_obj.goods_qty
  216. bound_obj.status = 1 # 批次状态为组盘完成
  217. print('批次id',bound_obj.id)
  218. bound_detail_obj = BoundDetailModel.objects.filter(bound_batch=bound_obj.id).first()
  219. if bound_detail_obj:
  220. bound_detail_obj.status = 1
  221. bound_detail_obj.save()
  222. print('入库申请id',bound_detail_obj.bound_list_id)
  223. # 入库申请全部批次入库完成
  224. bound_batch_all = BoundDetailModel.objects.filter(bound_list=bound_detail_obj.bound_list_id).all()
  225. if bound_batch_all.count() == bound_batch_all.filter(status=1).count():
  226. bound_list_obj = BoundListModel.objects.filter(id=bound_detail_obj.bound_list_id).first()
  227. print('当前状态',bound_list_obj.bound_status)
  228. bound_list_obj.bound_status = 102
  229. print('更新状态',bound_list_obj.bound_status)
  230. bound_list_obj.save()
  231. print('入库申请全部批次组盘完成')
  232. else:
  233. print('入库申请部分批次组盘完成')
  234. else:
  235. bound_obj.status = 0
  236. bound_obj.save() # 保存到数据库
  237. # 创建托盘详情记录(每个批次独立)
  238. print('新增个数',bound_obj.goods_in_qty-last_qty)
  239. if bound_obj.goods_in_qty-last_qty == goods_qty:
  240. detail_data = {
  241. "container": data['container'], # 托盘ID
  242. "batch": bound_obj.id, # 外键关联批次
  243. "goods_code": bound_obj.goods_code,
  244. "goods_desc": bound_obj.goods_desc,
  245. "goods_qty": goods_qty,
  246. "goods_weight": bound_obj.goods_weight,
  247. "status": 1,
  248. "month": data['month'],
  249. "creater": data.get('creater', 'zl') # 默认值兜底
  250. }
  251. serializer = self.get_serializer(data=detail_data)
  252. serializer.is_valid(raise_exception=True)
  253. serializer.save() # 必须保存到数据库
  254. operate_data = {
  255. "month" : data['month'],
  256. "container": data['container'], # 托盘ID
  257. "operation_type" : 'container',
  258. "batch" : bound_obj.id, # 外键关联批次
  259. "goods_code": bound_obj.goods_code,
  260. "goods_desc": bound_obj.goods_desc,
  261. "goods_qty": goods_qty,
  262. "goods_weight": bound_obj.goods_weight,
  263. "operator": data.get('creater', 'zl'), # 默认值兜底
  264. "timestamp": timezone.now(),
  265. "from_location": "container",
  266. "to_location": "container",
  267. "memo": "入库PDA组盘,pda入库"+str(bound_obj.goods_code)+"数量"+str(goods_qty)
  268. }
  269. serializer_operate = ContainerOperationPostSerializer(data=operate_data)
  270. serializer_operate.is_valid(raise_exception=True)
  271. serializer_operate.save() # 必须保存到数据库
  272. elif bound_obj.goods_in_qty-last_qty > 0:
  273. print('批次数量不一致')
  274. detail_data = {
  275. "container": data['container'], # 托盘ID
  276. "batch": bound_obj.id, # 外键关联批次
  277. "goods_code": bound_obj.goods_code,
  278. "goods_desc": bound_obj.goods_desc,
  279. "goods_qty": bound_obj.goods_in_qty-last_qty,
  280. "goods_weight": bound_obj.goods_weight,
  281. "status": 1,
  282. "month": data['month'],
  283. "creater": data.get('creater', 'zl') # 默认值兜底
  284. }
  285. serializer = self.get_serializer(data=detail_data)
  286. serializer.is_valid(raise_exception=True)
  287. serializer.save() # 必须保存到数据库
  288. operate_data = {
  289. "month" : data['month'],
  290. "container": data['container'], # 托盘ID
  291. "operation_type" : 'container',
  292. "batch" : bound_obj.id, # 外键关联批次
  293. "goods_code": bound_obj.goods_code,
  294. "goods_desc": bound_obj.goods_desc,
  295. "goods_qty": bound_obj.goods_in_qty-last_qty,
  296. "goods_weight": bound_obj.goods_weight,
  297. "operator": data.get('creater', 'zl'), # 默认值兜底
  298. "timestamp": timezone.now(),
  299. "from_location": "container",
  300. "to_location": "container",
  301. "memo": "入库PDA组盘,(数量不一致)pda入库"+str(bound_obj.goods_code)+"数量"+str(goods_qty)
  302. }
  303. serializer_operate = ContainerOperationPostSerializer(data=operate_data)
  304. serializer_operate.is_valid(raise_exception=True)
  305. serializer_operate.save() # 必须保存到数据库
  306. else :
  307. print('重复组盘')
  308. except Exception as e:
  309. print(f"更新批次 {bound_number} 失败: {str(e)}")
  310. continue
  311. # 将处理后的数据返回(或根据业务需求保存到数据库)
  312. res_data={
  313. "code": "200",
  314. "msg": "Success Create",
  315. "data": data
  316. }
  317. return Response(res_data, status=200)
  318. def update(self, request, pk):
  319. qs = self.get_object()
  320. data = self.request.data
  321. serializer = self.get_serializer(qs, data=data)
  322. serializer.is_valid(raise_exception=True)
  323. serializer.save()
  324. headers = self.get_success_headers(serializer.data)
  325. return Response(serializer.data, status=200, headers=headers)
  326. class ContainerOperateViewSet(viewsets.ModelViewSet):
  327. """
  328. retrieve:
  329. Response a data list(get)
  330. list:
  331. Response a data list(all)
  332. create:
  333. Create a data line(post)
  334. delete:
  335. Delete a data line(delete)
  336. """
  337. # authentication_classes = [] # 禁用所有认证类
  338. # permission_classes = [AllowAny] # 允许任意访问
  339. pagination_class = MyPageNumberPagination
  340. filter_backends = [DjangoFilterBackend, OrderingFilter, ]
  341. ordering_fields = ['id', "timestamp" ]
  342. filter_class = ContainerOperationFilter
  343. def get_project(self):
  344. try:
  345. id = self.kwargs.get('pk')
  346. return id
  347. except:
  348. return None
  349. def get_queryset(self):
  350. id = self.get_project()
  351. if self.request.user:
  352. if id is None:
  353. return ContainerOperationModel.objects.filter( is_delete=False)
  354. else:
  355. return ContainerOperationModel.objects.filter( id=id, is_delete=False)
  356. else:
  357. return ContainerOperationModel.objects.none()
  358. def get_serializer_class(self):
  359. if self.action in ['list', 'destroy','retrieve']:
  360. return ContainerOperationGetSerializer
  361. elif self.action in ['create', 'update']:
  362. return ContainerOperationPostSerializer
  363. else:
  364. return self.http_method_not_allowed(request=self.request)
  365. def create(self, request, *args, **kwargs):
  366. data = self.request.data
  367. serializer = self.get_serializer(data=data)
  368. serializer.is_valid(raise_exception=True)
  369. serializer.save()
  370. headers = self.get_success_headers(serializer.data)
  371. return Response(serializer.data, status=200, headers=headers)
  372. def update(self, request, pk):
  373. qs = self.get_object()
  374. data = self.request.data
  375. serializer = self.get_serializer(qs, data=data)
  376. serializer.is_valid(raise_exception=True)
  377. serializer.save()
  378. headers = self.get_success_headers(serializer.data)
  379. return Response(serializer.data, status=200, headers=headers)